“Currying” is a simple idea that is surprisingly powerful on the one hand,
and which was surprisingly hard (at least for me) to get my head around
- possibly because the concept didn’t exist natively in the languages I
learnt first.
When you declare a function in currying style, each argument is taken
one at a time, returning a new, more specialised function each time,
until the function is finally executed at the end.
Consider this function:
sub add ($left, $right) {
return $left + $right;
}
(Note we’re assuming that Perl has argument lists… which it can do
with Devel::Declare, but we’ll come to that in a bit). If this was
currying style then we wouldn’t call it with
my $answer = add (1, 3); # 4
but instead
my $answer = add(1) # a function with $left bound to 1
->(3) # now executed with $right bound to 3
Implementation
This is actually quite simple to implement in pure vanilla Perl.
sub add {
my $left = shift;
return sub {
my $right = shift;
return $left + $right;
};
}
That isn’t very pretty or convenient though… handily there are several
modules to encapsulate this behaviour on CPAN. One of them is my
Sub::Curried. The docs mention some of the other modules with
similar functionality: mine, which uses the shiny goodness of
Devel::Declare, has the advantage that you can declare a
curried subroutine with a simple, perlish syntax: in fact you do it more
or less exactly like the example I gave above. (The difference is that
we can’t override the sub keyword, so we create a new one,
‘curry‘:
curry add ($left, $right) {
return $left + $right;
}
Using D::D, the moment the Perl parser sees a symbol ‘curry’ being
compiled, it hands control to our custom parser, which then injects code
into the source while it’s still being compiled. We can do some cunning
stuff, including telling it “Hey, when you get to the end of the scope
you’re compiling, inject some more text!”
I used to keep hold of an array @filled of the partially
applied arguments and then apply all in one go at the end. But it seems
to be more elegant to actually transform into sometihng like the
“vanilla” example I gave above. I say “something like” but it’s
actually little more complicated:
sub add {
return ROUTINE unless @_; # a reference to this subroutine
check_args(2, @_); # check we weren't called with >2 args
my $f = sub {
my $left = shift;
return ROUTINE ...
check_args... # check we weren't called with >1 arg
my $f = sub {
my $right = shift;
return $left + $right; # actually do the thing
};
$f = ...
};
# now call the subroutine for each
$f = $f->(shift) for @_;
return $f;
}
Yikes! The extra boilerplate is there to make sure that we get some
niceties:
- Die with informative error message if we’re called with too many
arguments. - Handle being called with multiple arguments: i.e. treat add(1,2)
the same as add(1)->(2) - When called with zero arguments, the sub returned is logically (and
cutely!) an alias. (I think the ROUTINE trick isn’t needed, will
probably disappear with a restructure) - Handle functions that return multiple values smoothly (not shown
above)
Uses of currying
OK, so we’ve done a lot of furious work behind the scenes to make
something look very simple while doing a whole lot of extra work. But
why? When you program in Haskell, you’ll find currying useful at every
turn: it’s a hunch that it’d be useful in Perl too. There are certainly
some cute examples of it in common use:
Currying the invocant
Modules that do setup on a class would often use class methods: for
example:
package My::Class;
use base 'Class::Accessor';
__PACKAGE__->add_accessor('foo');
__PACKAGE__->add_accessor('bar');
__PACKAGE__->add_accessor('baz');
__PACKAGE__ refers to the current package, so this is the same as
writing:
My::Class->add_accessor('foo');
...
It’s also utterly hideous. Moose on the other hand provides a syntax
like this:
package My::Class;
use Moose;
has 'foo' => ...
has 'bar' => ...
has 'baz' => ...
What’s going on? Incredibly, ‘has’ is actually a class method just like
‘add_accessor’ was! But the leftmost argument (the invocant, usually
referred to as $self for object methods, or $class for
class methods) has been curried into it. This is because Perl’s
importing is dynamic and instead of just copying the method.
*{CALLER::has} = \&has;
It can do somethingl like this:
*{CALLER::has} = has($CALLER); # assuming a currying 'has'
Sections
In Haskell you can take references not just to functions, but to
operators.
add = (+) -- alias
add 1 2 -- result is 3
(+) 1 2 -- also 3
You can also take ‘sections’ of these operators, by ‘partially applying’
either the left or the right hand side.
add2 = (+ 2)
halve = (/ 2)
reciprocal = (1.0 /)
This isn’t the same as currying, though you could implement sections
with curried functions:
curry divide ($left, $right) {
$left / $right
}
my $reciprocal = divide(1); # 1 / $ARG
my $halve = flip(divide)->(2); # $ARG / 2
That’s rather ugly though, and remembering to flip the
arguments is annoying. So, again with Devel::Declare I
implemented
Sub::Section
(not yet on CPAN, the github repo is linked for now).
my $add2 = op(+ 2);
my $halve = op(/ 2);
my $contains_foo = op(=~ 'foo');
And of course:
my $greet = op("Hello " .);
say $greet->('World');
Talk
I’ll be talking about Functional Perl at the
href="http://northwestengland.pm.org/meetings/004.html">NorthWestEngland
perlmongers tomorrow Tues 5th in Manchester, UK.