FunctionalPerl

 view release on metacpan or  search on metacpan

lib/FP/Currying.pm  view on Meta::CPAN

package FP::Currying;
use strict;
use warnings;
use warnings FATAL => 'uninitialized';
use Exporter "import";

our @EXPORT = qw(
    curry
    curry_
    partial
    uncurry
    uncurry_1_1
    uncurry_2_1
    uncurry_1_2
    uncurry_2_2
    uncurry_1_1_1
);
our @EXPORT_OK   = qw();
our %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]);

use FP::Carp;

sub curry {
    @_ == 1 or fp_croak_arity 1;
    my ($f) = @_;
    sub {
        @_ == 1 or fp_croak_arity 1;
        my ($a) = @_;
        sub {
            @_ == 1 or fp_croak_arity 1;
            @_ = ($a, @_);
            goto \&$f
        }
    }
}

# relaxed version
sub curry_ {
    my ($f, @p) = @_;
    sub {
        my @a = @_;
        sub {
            @_ = (@p, @a, @_);
            goto \&$f
        }
    }
}

# https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj
# "Takes a function f and fewer than the normal arguments to f, and
# returns a fn that takes a variable number of additional args. When
# called, the returned function calls f with args + additional args."
sub partial {
    my ($f, @p) = @_;
    sub {
        @_ = (@p, @_);
        goto \&$f
    }
}

# Macros would be useful here.

sub uncurry_1_1 {
    @_ == 1 or fp_croak_arity 1;
    my ($f) = @_;
    sub {
        @_ == 2 or fp_croak_arity 2;
        my ($a, $b) = @_;
        $f->($a)->($b)
    }
}

sub uncurry;
*uncurry = \&uncurry_1_1;

sub uncurry_2_1 {
    @_ == 1 or fp_croak_arity 1;
    my ($f) = @_;
    sub {
        @_ == 3 or fp_croak_arity 3;
        my ($a, $b, $c) = @_;
        $f->($a, $b)->($c)
    }
}

sub uncurry_1_2 {
    @_ == 1 or fp_croak_arity 1;
    my ($f) = @_;
    sub {
        @_ == 3 or fp_croak_arity 3;
        my ($a, $b, $c) = @_;
        $f->($a)->($b, $c)
    }
}

sub uncurry_2_2 {
    @_ == 1 or fp_croak_arity 1;
    my ($f) = @_;
    sub {
        @_ == 4 or fp_croak_arity 4;
        my ($a, $b, $c, $d) = @_;
        $f->($a, $b)->($c, $d)
    }
}

sub uncurry_1_1_1 {
    @_ == 1 or fp_croak_arity 1;
    my ($f) = @_;
    sub {
        @_ == 3 or fp_croak_arity 3;
        my ($a, $b, $c) = @_;
        $f->($a)->($b)->($c)
    }
}

# ...

1



( run in 3.259 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )