PrePAN

Sign in to PrePAN

PartialApplication A small module that handle partially applying parameters to functions

Good

Synopsis

use PartialApplication qw( partiallyApply );

sub concatenate {
    print join(" ", @_) . "\n";
}

my $greet = partiallyApply( \&concatenate, "hello" );

$greet->("world");

Description

PartialApplilcation is a small module to handle partially applying parameters to functions - a common technique used in the functional programming style of coding.

FUNCTIONS

partiallyApply( \&function, @parameters )

Partially applies the parameters to the function, giving a new function reference.

To partially apply parameters to an object method, pass a function reference to the method as the first parameter, the object instance as the second, followed by the parameters to be partially applied.

my $object = Class->new();

my $partiallyAppliedMethod = partiallyApply( \&Class::method, $object, 1, 2, 3 );

$partiallyAppliedMethod->(4, 5, 6);   # equivilant of $object->method(1, 2, 3, 4, 5, 6)

RETURNS

A function reference to the partially applied function.

partiallyApplyRight( \&function, @parameters )

Partially applies the parameters to the end of the function call - useful for when you're using named parameters and you want to make sure that the partially applied parameters are the ones used.

sub testSub {
    my %params = @_;

    print "$_ - $params{$_}\n" for keys %params;
}

my $partiallyAppliedFunction = partiallyApplyRight( \&testSub, asdf => 99 );

$partiallyAppliedFunction->(asdf => 100);   # outputs: asdf - 99

RETURNS

A function reference to the partially applied function.

partiallyApplyN( \&function, \@parameterBitmap, @parameters )

Partially applies the parameters based upon the parameterBitmap. An entry of 1 in the parameterBitmap will use a partially applied parameter and an entry of 0 will use a parameter from the call.

sub testSub {
    print join(", ", @_) ."\n";
}

my $partiallyAppliedFunction = partiallyApplyN( \&testSub, [ 1, 0, 1, 0 ], 1, 2, 3, 4, 5 );

$partiallyAppliedFunction->('a', 'b', 'c', 'd'); # outputs: 1, a, 2, b, 3, 4, 5, c, d

This does allow you to partially apply parameter to a method call without specifying the object instance to apply it to multiple instances.

my $partiallyAppliedMethod2 = partiallyApplyN( \&Class::method, [ 0, 1, 1, 1 ], 1, 2, 3 );

$partiallyAppliedMethod2->($object1, 4, 5); # equivilant to $object1->method(1, 2, 3, 4, 5)
$partiallyAppliedMethod2->($object2, 6, 7); # equivilant to $object2->method(1, 2, 3, 6, 7)

RETURNS

A function reference to the partially applied function.

Comments

anonymouse
Anonymous
The technique is known as "currying".
You can find a partial list of existing perl solutions in the SEE ALSO section here:
https://metacpan.org/pod/distribution/Sub-Curried/lib/Sub/Curried.pm#SEE-ALSO
There's probably many more.
Thanks for the comment. While the technique is sometimes mistakenly referred to as Currying, it is called Partial Application.

Currying is where a function that takes X number of parameters and returns an answer, is converted in to in a chain of functions where each takes 1 parameter and return a function until the last one in the chain is called which returns the answer (see Wikipedia for a more in depth explanation https://en.wikipedia.org/wiki/Currying).

In the past I've looked at the following modules for Partial Application, but none of them worked well in my environment:

* curry [https://metacpan.org/pod/curry] - Partial application but only seems to work on object methods

* Sub::Curried [https://metacpan.org/pod/Sub::Curried] - Actually lets you declare curried functions. It does have has limited abilities to do Partial Application, but you have to declare the number of parameters the function takes.

* Sub::Curry [https://metacpan.org/pod/Sub::Curry] - More heavyweight/complex than a lot of people need/want.

* Sub::DefferedPartial [https://metacpan.org/pod/Sub::DeferredPartial] - Partial Application for named parameters (i.e. hash parameters).

* Autocurry [https://metacpan.org/pod/AutoCurry] - Lets you do Partial Application but in a way that just doesn't make sense to me.

* Attribute::Curried [https://metacpan.org/pod/Attribute::Curried] - Lets you define a function as being curried. Again it has limited abilities to do Partial Application, but you have to declare the number of parameters.

* Perl6.Currying [https://metacpan.org/pod/Perl6::Currying] - Does Partial Application, but requires the functions to be specially prototyped.

Please sign up to post a review.