The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

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)