Rit*_*ose 4 perl functional-programming
你怎么样:
有一个sub回报sub
要么
将文本作为代码执行
在Perl?
另外,我如何拥有匿名函数存储状态?
Eth*_*her 16
sub返回一个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;
}
Run Code Online (Sandbox Code Playgroud)
可以使用该eval函数执行任意文本:请参阅perldoc -f eval中的文档:
eval q{print "hello world!\n"};
Run Code Online (Sandbox Code Playgroud)
请注意,如果您正在评估从用户输入中提取的任何内容,这是非常危险的,并且通常是一种不好的做法,因为您通常可以在coderef中定义代码,如上面的示例中所示.
您可以使用状态变量(perl5.10中的new)或带有高于sub本身的变量作为闭包来存储状态:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
返回子程序引用.
这是一个简单的例子,它创建了一个关闭值的子引用:
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; };
}
Run Code Online (Sandbox Code Playgroud)
你也可以像这样使用命名的subs:
sub op {
my $name = shift;
return $op eq 'add' ? \&add : sub {};
}
sub add {
my $l = shift;
my $r = shift;
return $l + $r;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用eval任意字符串,但不要使用它.代码很难读取,它重新启动编译,这会减慢所有内容.有少数情况下,字符串评估是工作的最佳工具.任何时候字符串评估似乎都是一个好主意,你几乎肯定会用另一种方法更好.
几乎任何你想用字符串eval做的事情都可以用闭包来实现.
使用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";
}
Run Code Online (Sandbox Code Playgroud)
5.10引入了状态变量.
使用Perl执行文本是完成的eval EXPR:
EXPR解析并执行返回值就像它是一个小的Perl程序一样.首先解析表达式的值(它本身在标量上下文中确定),如果没有任何错误,则在当前Perl程序的词汇上下文中执行,以便之后保留任何变量设置或子例程和格式定义.请注意,每次eval执行时都会解析该值
执行任意字符串将打开巨大的安全漏洞.
您可以创建匿名子例程并通过引用访问它们; 这个引用当然可以分配给标量:
my $subref = sub { ... code ... }
Run Code Online (Sandbox Code Playgroud)
或从另一个子程序返回
return sub { ... code ... }
Run Code Online (Sandbox Code Playgroud)
如果需要存储状态,可以使用外部作用域中定义的词法变量创建闭包,如:
sub create_func {
my $state;
return sub { ... code that can refer to $state ... }
}
Run Code Online (Sandbox Code Playgroud)
您可以使用eval运行代码