Passing a Function Object and Calling it

Tag: perl , reference Author: ganjunqitc Date: 2009-07-20

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

Other Answer1

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

comments:

What if I was passing the function as part of a hash, then would it look like this? $args{function}->();
I've added examples for array and hash references.
But what if it was this: f(function => \&func); then in the function, f, would it be this? sub f { $args{function}->(); }
Kys: Yes, '->()' dereferences a code reference and calls it. Arguments to the function go between the parens, as you'd expect.
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.

Other Answer2

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!

comments:

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

Other Answer3

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.

Other Answer4

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