How can I code a functional style in Perl?

How are you:

  • have sub return a sub

    or

  • execute text as code

in perl?

Also, how can I get the state of anonymous state of a function?

+4
source share
4 answers

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

Custom text can be executed using the eval function: see the documentation for 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 it is usually bad practice, as you can usually define your code in the encoder, as in the previous examples above.

You can save state with a state variable (new in perl5.10) or with a variable, an area higher than the sub itself, as 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; } } 
+16
source

Return subroutine reference.

Here is a simple example that creates sub refs closed above 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 subs names like:

 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 do not do this. The code is hard to read, and it restarts compilation, which slows everything down. There are few cases where the eval string is the best tool to work with. Whenever an eval string seems like a good idea, you will almost certainly be better off with a different approach.

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

+7
source

Returning submarines are easy to use with the sub keyword. The returned unit is closed over the lexical variables that 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 .

Perl text execution is done using eval EXPR :

the EXPR return value is parsed and executed as if it were a small Perl program. The value of the expression (which is itself determined in the scalar context) is first analyzed, and if there were no errors being performed in the lexical context of the current Perl program, so after that any parameters of the variables or definitions of subprograms and formats remain after that, Note that the value is analyzed each time that eval executes

Performing arbitrary strings will open up huge security holes.

+5
source

You can create anonymous routines and access them through a link; Of course, this link can be assigned to a scalar:

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

or returns from another routine

 return sub { ... code ... } 

If you need to save states, you can create closures with lexical variables defined in the outer scope, for example:

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

You can run the code with eval

+5
source

Source: https://habr.com/ru/post/1300209/


All Articles