views:

155

answers:

4

How do you either:

  1. have a sub return a sub

    or

  2. execute text as code

in Perl?

Also, how do I have an anonymous function store state?

+16  A: 

A sub returns a sub as a 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;
}

Arbitrary text can be executed with the eval function: see the documentation at perldoc -f eval:

eval q{print "hello world!\n"};

Note that this is very dangerous if you are evaluating anything extracted from user input, and is generally a poor practice anyway as you can generally define your code in a coderef as in the earlier examples above.

You can store state with a state variable (new in perl5.10), or with a variable scoped higher than the sub itself, as a 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;
    }
}
Ether
String `eval` is almost always a bad idea, tough. The only place where it makes sense that I can think of off the top of my head is to `require` a module with bareword semantics: `eval "require $module";`. I know there have to be a few other cases where it makes sense, but my point is that they are few and far between.
daotoad
Absolutely. Beginners seize on the idea of 'eval' as a hammer to bash all nails, whereas it is actually a tool that is best kept at the very bottom of the toolbox for rare circumstances.
Ether
@Ether http://xkcd.com/327/
piggles
+7  A: 

Return a subroutine reference.

Here's a simple example that creates sub refs closed over a value:

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; };

}

You can also work with named subs like this:

sub op {
    my $name = shift;

    return $op eq 'add' ? \&add : sub {};
}

sub add {
    my $l = shift;
    my $r = shift;

    return $l + $r; 
}

You can use eval with an arbitrary string, but don't do it. The code is hard to read and it restarts compilation, which slows everything down. There are a small number of cases where string eval is the best tool for the job. Any time string eval seems like a good idea, you are almost certainly better off with another approach.

Almost anything you would like to do with string eval can be achieved with closures.

daotoad
+5  A: 

Returning subs is easy by using the sub keyword. The returned sub closes over the lexical variables it uses:

#!/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 introduced state variables.

Executing text as Perl is accomplished using eval EXPR:

the return value of EXPR is parsed and executed as if it were a little Perl program. The value of the expression (which is itself determined within scalar context) is first parsed, and if there weren't any errors, executed in the lexical context of the current Perl program, so that any variable settings or subroutine and format definitions remain afterwards. Note that the value is parsed every time the eval executes

Executing arbitrary strings will open up huge gaping security holes.

Sinan Ünür
+5  A: 

You can create anonymous subroutines and access them via a reference; this reference can of course be assigned to a scalar:

my $subref = sub { ... code ... }

or returned from another subroutine

return sub { ... code ... }

If you need to store states, you can create closures with lexical variables defined in an outer scope like:

sub create_func {
    my $state;
    return sub { ... code that can refer to $state ... }
}

You can run code with eval

kemp