Kys
Kys

Reputation: 2635

Passing a Function Object and Calling it

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

Upvotes: 33

Views: 19809

Answers (4)

Michael Carman
Michael Carman

Reputation: 30851

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.

Upvotes: 10

Eli Courtwright
Eli Courtwright

Reputation: 193201

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

Upvotes: 49

hillu
hillu

Reputation: 9631

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

Upvotes: 4

mixonic
mixonic

Reputation: 2701

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!

Upvotes: 4

Related Questions