有没有更好的方式,通过参考在Perl通过?
-
20-09-2019 - |
题
我做通按引用这样的:
use strict;
use warnings;
sub repl {
local *line = \$_[0]; our $line;
$line = "new value";
}
sub doRepl {
my ($replFunc) = @_;
my $foo = "old value";
$replFunc->($foo);
print $foo; # prints "new value";
}
doRepl(\&repl);
是否有这样做的更清洁的方式?
由于我使用的是函数引用(相信我,有一个很好的理由,使用函数引用)的原型不工作。
我也不想在$_[0]
到处使用repl
,因为它是丑陋的。
解决方案
让你看着数据::别名?它可以让你有一个清晰的语法词法创建范围的别名。
可以使用它来创建通引用语义如下:
use strict;
use warnings;
use Data::Alias;
sub foo {
alias my ($arg) = @_;
$arg++;
}
my $count = 0;
foo($count);
print "$count\n";
的输出是1
,指示呼叫到foo
改性它的参数。
其他提示
sub repl {
my $line = \$_[0]; # or: my $line = \shift
$$line = "new value";
}
有几个方法可以做到这一点。明确地通过一个标量裁判$foo
,或通过引用语义利用Perl的内置通。
显式引用:
my $foo = "old value";
doRepl( \&repl, \$foo );
print $foo; # prints "new value";
sub repl {
my $line = shift;
$$line = "new value";
}
sub doRepl {
my ($replFunc, $foo) = @_;
$replFunc->($foo);
}
通过引用传递:
my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";
sub repl {
$_[0] = "new value";
}
sub doRepl {
my $replFunc = shift;
$replFunc->(@_);
}
通过引用即使发烧友通:
my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";
sub repl {
$_[0] = "new value";
}
sub doRepl {
my $replFunc = shift;
&$replFunc;
}
第一个使用普通的perl硬引用来完成这项工作。
在第一遍通过参考方法使用是Perl参数传递给所有用作参考的事实。 @_
的元素实际上是别名在参数列表中的值时,则子程序调用。通过在$_[0]
改变foo()
,实际上改变到foo()
第一个参数。
在第二遍通过参考方法利用一个事实,即所谓带有印记&
和没有括号子得到其呼叫者的@_
阵列。否则,它是相同的。
更新:我只注意到你的愿望,以避免$_[0]
。您可以在REPL做到这一点,如果你想:
sub repl {
for my $line( $_[0] ) {
$line = 'new value';
}
}
我不认为这有什么错误使用local
建立在这种情况下别名。
动态范围当然是一个强大的功能,但只要你是知道的副作用(新值在其范围内调用函数可见,如果同名的词汇是在范围上,它不能是局部的,...),那么它是一种有用的除了已经溢出的Perl工具箱。
在约local
Perl的文档警告的主要原因是保持无意中使用它,而不是my
人,以缓解从Perl4样式的转变。但也有一定的时间时local
是有用的,并且这是一个。
使用for
创建您的别名也是一种选择,但我发现,在其意图更清晰local
明确语法。它也有点更快,如果性能是一个问题。
不隶属于 StackOverflow