你是怎么做的:
sub
返回sub
或
执行文本代码
?
另外,我如何拥有匿名函数存储状态?
答案 0 :(得分:16)
sub将子返回为 coderef :
# example 1: return a sub that is defined inline.
sub foo
{
return sub {
my $this = shift;
my @other_params = @_;
do_stuff();
return $some_value;
};
}
# example 2: return a sub that is defined elsewhere.
sub bar
{
return \&foo;
}
可以使用eval
函数执行任意文本:请参阅perldoc -f eval上的文档:
eval q{print "hello world!\n"};
请注意,如果您正在评估从用户输入中提取的任何内容,那么非常危险,并且通常是一种不好的做法,因为您通常可以在coderef中定义代码,如上面的示例所示。
您可以使用state variable(perl5.10中的新内容)或使用高于子本身的变量作为closure来存储状态:
use feature 'state';
sub baz
{
state $x;
return ++$x;
}
# create a new scope so that $y is not visible to other functions in this package
{
my $y;
sub quux
{
return ++$y;
}
}
答案 1 :(得分:7)
返回子程序参考。
这是一个简单的例子,它创建了一个关闭值的子引用:
my $add_5_to = add_x_to(5);
print $add_5_to->(7), "\n";
sub add_x_to {
my $x = shift;
return sub { my $value = shift; return $x + $value; };
}
你也可以像这样使用命名的潜水员:
sub op {
my $name = shift;
return $op eq 'add' ? \&add : sub {};
}
sub add {
my $l = shift;
my $r = shift;
return $l + $r;
}
您可以将eval
与任意字符串一起使用,但不要这样做。代码很难读取,并重新启动编译,这会减慢所有内容。有少数情况下,字符串评估是工作的最佳工具。任何时候字符串评估似乎都是一个好主意,你几乎肯定会用另一种方法更好。
使用闭包几乎可以实现对字符串eval的任何操作。
答案 2 :(得分:5)
使用sub
关键字可以轻松返回潜艇。返回的子关闭它使用的词法变量:
#!/usr/bin/perl
use strict; use warnings;
sub mk_count_from_to {
my ($from, $to) = @_;
return sub {
return if $from > $to;
return $from ++;
};
}
my $c = mk_count_from_to(-5, 5);
while ( defined( my $n = $c->() ) ) {
print "$n\n";
}
5.10介绍了state variables。
完成将文本作为Perl执行解析并执行
EXPR
的返回值,就像它是一个小的Perl程序一样。首先解析表达式的值(它本身在标量上下文中确定),如果没有任何错误,则在当前Perl程序的词汇上下文中执行,以便之后保留任何变量设置或子例程和格式定义。请注意,每次执行eval
时都会解析该值
执行任意字符串将打开巨大的安全漏洞。
答案 3 :(得分:5)
您可以创建匿名子程序并通过引用访问它们;这个引用当然可以分配给标量:
my $subref = sub { ... code ... }
或从其他子程序返回
return sub { ... code ... }
如果需要存储状态,可以使用外部作用域中定义的词法变量创建闭包,如:
sub create_func {
my $state;
return sub { ... code that can refer to $state ... }
}
您可以使用eval
运行代码