NAME
Perl6::Currying - Perl 6 curried closure syntax for Perl 5
VERSION
This document describes version 0.01 of Perl6::Currying, released May 14, 2002.
SYNOPSIS
use Perl6::Currying;
my $add = { $^a + $^b }; # Create a HOF that adds its two args
print $add->(1,2), "\n"; # Call it
my $incr = $add->(1); # Bind the $x argument to 1
# to create an increment HOF
print $incr->(3), "\n"; # Increment a number
@data{0..10} = ('A'..'Z');
# Use HOFs as map, grep, and sort blocks
print join ",", sort { $^y <=> $^x } 1..10;
print join "\n", map { $^value**2 } 1..10;
print join "\n", map { $data{$_-1}.$^value**2 } 1..10;
print join "\n", grep { $data{$^value} } 1..10;
my $div = { $^x / $^y }; # Create a HOF that divides its two args
print $div->(1,2), "\n"; # Do a division
my $half = $div->({y=>2}); # Bind the denominator to 2
# to create a halving HOF
print $half->(42), "\n"; # Half of something
print $half->({x=>42}), "\n"; # Same thing via binding
my $twelfth = $half->({y=>12}); # Rebind the denominator
print $twelfth->(24), "\n"; # A twelfth of something
my $bad = $half->({q=>12}), "\n"; # Error: no such parameter
DESCRIPTION
The Perl6::Currying module lets you try out the new Perl 6 implicit higher-order function syntax in Perl 5.
Perl 6 reserves all variables of the form $^name
as "placeholders" that can be used to generate higher order functions.
Any block containing one or more such placeholders is treated as a reference to a subroutine in which the placeholders are replaced by the appropriate number and sequence of arguments.
That is, the expression:
# Perl 6 code
$check = { $^a == $^b**2 * $^c or die $^err_msg };
is equivalent to:
# Perl 6 code
$check = sub ($a, $b, $c, $err_msg) {
$a == $b**2 * $c or die $err_msg
};
This could then be invoked:
# Perl 6 code
$check.($i,$j,$k,$msg);
It is also be possible to interpolate an argument list into a static expression like so:
# Perl 6 code
{ $^a == $^b**2 * $^c or die $^err_msg }.($i,$j,$k,$msg);
The placeholders are sorted ASCIIbetically before they are used to create the subroutine's parameter list. Hence the following:
# Perl 6 code
@reverse_sorted = sort {$^b <=> $^a} @list;
works as expected. That is, it's equivalent to:
@reverse_sorted = sort sub($a,$b){$b <=> $a}, @list;
Re-currying deferred expressions
The subroutines generated by a placeholder are not exactly like the equivalent subroutines shown above. If they are called with fewer than the required number of arguments, they return another higher order function, which now has the specified arguments fixed ("bound") to the values given.
Thus:
# Perl 6 code
$check_or_die = $check.($i,$j,$k); # 3 args, not 4
produces another deferred expression, one that requires only a single argument:
# Perl 6 code
$check_or_die.("Error message");
Arguments can also be bound by the use of named arguments. This allows arguments other than the first to be bound as well:
# Perl 6 code
$check_msg = $check->(err_msg=>"Check failed");
# and later...
$check_msg.($i,$j,$k);
Declaring curried closures in Perl 5
The Perl6::Currying module allows you to use (almost) the same syntax in Perl 5.
That is, the expression:
# Perl 5 code
use Perl6::Currying;
$check = { $^a == $^b**2 * $^c or die $^err_msg };
is equivalent to:
# Perl 5 code
$check = sub (;$$$$) {
my ($a, $b, $c, $err_msg) = @_;
$a == $b**2 * $c or die $err_msg;
};
This could then be invoked:
# Perl 5 code
$check->($i,$j,$k,$msg);
It is also be possible to interpolate an argument list into a static expression like so:
# Perl 5 code
use Perl6::Currying;
{ $^a == $^b**2 * $^c or die $^err_msg }->($i,$j,$k,$msg);
The placeholders are sorted ASCIIbetically before they are used to create the subroutine's parameter list. Hence the following:
# Perl 5 code
use Perl6::Currying;
@reverse_sorted = sort {$^b <=> $^a} @list;
works as expected (even in earlier perls that don't support sub refs as sort specifiers!)
Re-currying deferred expressions
The Perl 5 subroutines generated using placeholders are genuine higher order functions (just as they'll be in Perl 6).
In particular, if they are called with fewer than the required number of arguments, they return another higher order function, which now has the specified arguments bound to the values given.
Thus:
# Perl 5 code
$check_or_die = $check->($i,$j,$k); # 3 args, not 4
produces another deferred expression, one that requires only a single argument:
# Perl 5 code
$check_or_die->("Error message");
Arguments can also be bound by the use of named arguments, just as in Perl 6. However, in Perl 5, these named arguments have to be specified in a single anonymous hash:
# Perl 5 code
$check_msg = $check->({err_msg=>"Check failed"});
# and later...
$check_msg->($i,$j,$k);
REFERENCES
A quick introduction: http://www.tunes.org/~iepos/introduction-to-logic/chap00/sect00.html
Definition of currying: http://www.cs.nott.ac.uk/~gmh//faq.html#currying
Implementation in Haskell: http://www.haskell.org/tutorial/functions.html
DEPENDENCIES
The module is implemented using Filter::Simple and requires that module to be installed.
AUTHOR
Damian Conway (damian@conway.org)
BUGS
This module is not designed for serious implementation work.
It uses some relatively sophisticated heuristics to translate Perl 6 syntax back to Perl 5. It will make mistakes if your code gets even moderately tricky.
Nevertheless, bug reports are most welcome.
COPYRIGHT
Copyright (c) 2001, Damian Conway. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the terms of the Perl Artistic License (see http://www.perl.com/perl/misc/Artistic.html)