Sawyer Sawyer - 2 months ago 10
Perl Question

How can I do function partial application in Perl?

Is there any way to achieve partial application in Perl?

Suppose, I want to do something like:

sub each_file($arr, $op) {
$op->($_) for @{$arr};
...
}

sub each_line($op, $file) {
...
}

each_file($arr, each_line($op));


I want to partially apply
each_line()
to only
$op
, so it'll become a new function can be passed to
$each_file
, how do I express this in idiomatic Perl?

Answer

You can do this in Perl with two approaches combined:

  • A function which returns a function reference

  • Closures

Example:

sub each_file {
    my ($arr, $line_fn) = @_;
    $line_fn->($_) for @{$arr};
    ...
} 

sub each_line {
    my ($op, $file) = @_;
    ... 
}

sub make_line_processor {
  my ( $op ) = @_;

  # This is closed over $op, which effectively becomes 
  # a constant for the returned function
  my $fn = sub {
     return each_line( $op, @_ );
  };
  return $fn;
}


# To call it:
each_file( $arr, make_line_processor($op) );

This can be an even more useful technique in cases where you don't want $op directly, but some expensive-to-fetch derivation of it. In which case you would calculate the derived value just once (in the make_line_processor function) and close over that instead.