Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run an anonymous function in Perl?

Tags:

perl

(sub { print 1; })();    sub { print 1; }(); 

I tried various ways, all are wrong...

like image 951
asker Avatar asked Sep 08 '11 05:09

asker


2 Answers

(sub { ... }) will give you the pointer to the function so you must call by reference.

(sub { print "Hello world\n" })->();

The other easy method, as pointed out by Blagovest Buyukliev would be to dereference the function pointer and call that using the { } operators

&{ sub { print "Hello World" }}();

like image 93
zellio Avatar answered Oct 03 '22 23:10

zellio


Yay, I didn't expect you folks to come up with that much possibilities. But you're right, this is perl and TIMTOWTDI: +1 for creativitiy!

But to be honest, I use hardly another form than the following:

The Basic Syntax

my $greet = sub {     my ( $name ) = @_;     print "Hello $name\n"; };  # ...  $greet->( 'asker' ) 

It's pretty straight forward: sub {} returns a reference to a sub routine, which you can store and pass around like any other scalar. You can than call it by dereferencing. There is also a second syntax to dereference: &{ $sub }( 'asker' ), but I personally prefer the arrow syntax, because I find it more readable and it pretty much aligns with dereferencing hashes $hash->{ $key } and arrays $array->[ $index ]. More information on references can be found in perldoc perlref.

I think the other given examples are a bit advanced, but why not have a look at them:

Goto

sub bar {goto $foo}; bar; 

Rarely seen and much feared these days. But at least it's a goto &function, which is considered less harmful than it's crooked friends: goto LABEL or goto EXPRESSION ( they are deprecated since 5.12 and raise a warning ). There are actually some circumstances, when you want to use that form, because this is not a usual function call. The calling function ( bar in the given example ) will not appear in the callling stack. And you don't pass your parameters, but the current @_ will be used. Have a look at this:

use Carp qw( cluck );  my $cluck = sub {     my ( $message ) = @_;     cluck $message . "\n"; };   sub invisible {     @_ = ( 'fake' );     goto $cluck; }  invisible( 'real' ); 

Output:

fake at bar.pl line 5     main::__ANON__('fake') called at bar.pl line 14 

And there is no hint of an invisible function in the stack trace. More info on goto in perldoc -f goto.

Method Calls

''->$foo; # or undef->$foo; 

If you call a method on an object, the first parameter passed to that method will be the invocant ( usually an instance or the class name ). Did i already say that TIMTOWTCallAFunction?

# this is just a normal named sub sub ask {     my ( $name, $question ) = @_;     print "$question, $name?\n"; };  my $ask = \&ask; # lets take a reference to that sub   my $question = "What's up";  'asker'->ask( $question ); # 1: doesn't work  my $meth_name = 'ask'; 'asker'->$meth_name( $question ); # 2: doesn't work either  'asker'->$ask( $question ); # 1: this works 

In the snippet above are two calls, which won't work, because perl will try to find a method called ask in package asker ( actually it would work if that code was in the said package ). But the third one succeeds, because you already give perl the right method and it doesn't need to search for it. As always: more info in the perldoc I can't find any reason right now, to excuse this in production code.

Conclusion

Originally I didn't intend to write that much, but I think it's important to have the common solution at the beginning of an answer and some explanations to the unusual constructs. I admit to be kind of selfish here: Every one of us could end up maintaining someones code, who found this question and just copied the topmost example.

like image 41
Egga Hartung Avatar answered Oct 03 '22 22:10

Egga Hartung