views:

153

answers:

4

How do I pass a function, a, to function, b, and have b call a in Perl?

+12  A: 

Here's a complete, working script that demonstrates what you're asking.

sub a { print "Hello World!\n"; }

sub b {
    my $func = $_[0];
    $func->();
}

b(\&a);

Here's an explanation: you take a reference to function a by saying \&a. At that point you have a function reference; while normally a function would be called by saying func() you call a function reference by saying $func->()

The -> syntax deal with other references as well. For example, here's an example of dealing with array and hash references:

sub f {
    my ($aref, $href) = @_;
    print "Here's an array reference: $aref->[0]\n";  # prints 5
    print "Here's a hash ref: $href->{hello}\n";      # prints "world"
}

my @a = (5, 6, 7);
my %h = (hello=>"world", goodbye=>"girl");
f(\@a, \%h);
Eli Courtwright
What if I was passing the function as part of a hash, then would it look like this?$args{function}->();
Kys
I've added examples for array and hash references.
Eli Courtwright
But what if it was this:f(function => \then in the function, f, would it be this?sub f { $args{function}->();}
Kys
Kys: Yes, '->()' dereferences a code reference and calls it. Arguments to the function go between the parens, as you'd expect.
runrig
function calls follow the same rules as other chained dereferences, so you can discard the arrow and say `$args{function}()`;, but that can be a little confusing.
Chas. Owens
+1  A: 

Hi Kys,

You can access subroutines references as \&my_method in Perl, and call those references with $myref->();. Try this:

perl -e'sub a { print "foo in a"; }; sub b { shift->(); }; b(\&a);'

Good luck!

mixonic
What if I was passing the function as part of a hash, then would it look like this? $args{function}->();
Kys
+1  A: 

Following up to Eli Courtwright's example: If you only use the first function once, you could also call b with an anonymous function, like this:

b( sub { print "Hello World\n"; } );
hillu
+1  A: 

You can't pass a function to another function directly. Instead, you pass a reference to a function. To call the function you dereference it (as a CODE ref) using ->();

sub a { print @_ }

sub b {
  my $f = shift;  # assuming that $f is a function reference...
  $f->(@_);       # call it with the remaining arguments
}

b(\&a, "hello, world!");  # prints "hello, world!"

Perl doesn't have pass-by-name semantics but you can emulate them using a hash. The method for calling the function is the same. You dereference it.

sub a { print @_ }

sub b {
    my %arg = @_;
    $arg{function}->(@{$arg{arguments}});
}

b(function => \&a, arguments => ["hello, world!"]);

ObPerl6: Perl 6 will have pass-by-name semantics.

Michael Carman