如何在Perl中使用函数样式进行编码?

时间:2010-02-03 17:37:15

标签: perl functional-programming

你是怎么做的:

  1. sub返回sub

  2. 执行文本代码

  3. 在Perl中

    另外,我如何拥有匿名函数存储状态?

4 个答案:

答案 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

使用eval EXPR

完成将文本作为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

运行代码