我不明白左值子例程的用途是什么?什么是我用普通子程序无法完成的?你能发布一些例子吗?
谢谢
您可以使用左值子作为对象成员的设置器:
sub x : lvalue {
my $self = shift;
$self->{x};
}
然后后来:
$foo->x = 5;
这结合了直接设置成员的直观性和封装 setter 的灵活性,以防您以后想要更改对象的实现方式。与以下在 Perl 中设置成员的更传统方法相比:
直觉但脆弱;如果你改变 $foo 的实现方式会怎样?
$foo->{x} = 5;
传统的setter方法;不使用赋值语法来表示赋值:
$foo->set_x(5);
当然,Perl 社区从未真正接受过左值方法,并且使用左值 subs 是“奇怪的”,任何为了直观而获得的东西都会因为这一切的陌生而丢失。
建议避免使用 LValue。它们很有趣,但它们会让新用户感到困惑,因为他们会假设所有 subs 是如何工作的,因此当有更好的方法可用时,应该在代码中避免它。
有时使用 LValue 结果来做脏活是非常实用的。
substr( $string, $start, $stop ) = 'somevalue' # replaces the specified part of the substring.
但是,这也做同样的事情:
substr( $string, $start, $stop , 'somevalue' );
这里的区别主要是前者具有更强的表达能力,因为它将行为委托给使用它的代码而不是函数本身。
例如:
substr( $string, $start, $stop ) =~ s/a/b/g
会要求你做
my $x = substr( $string, $start, $stop );
$x =~ s/a/b/g/;
substr( $string, $start, $stop, $x );
这有点讨厌。
虽然,这里还有一个令人讨厌的地方,因为您必须考虑是否使用 $x 进行替换是否可以追溯修改字符串(因为 substr 是 LValue 子)。我不认为它有,但它不够模糊,我必须检查手册才能记住它是否有,这很糟糕。
它们提供了不同的界面,在某些情况下可以更直观。与传统的 setter 不同,您实际上可以直接更改值。例如
lvalue_sub($foo) =~ s/foo/bar/;
可以比
my $tmp = some_sub($foo);
$tmp =~ s/foo/bar/;
some_sub($foo, $tmp);
我不能说在我的普通 Perl 东西中大量使用它们,但是在获取切片或 piddle 的其他小节时,它们在 Perl 数据语言中被广泛使用。例如:
my $a = sequence(100);
# use lvalue in this increment:
$a->where($a < 10)++;
# Zero-out the last four elements
# notice the use of the overloaded .= operator:
$a->slice("-10:") .= 0;
与 Perl 中的许多东西一样,这个特性在整个生态系统中的使用并不多,但它至少在这个利基市场中的使用让 PDL 用户的生活变得更加轻松。