FAST
view release on metacpan or search on metacpan
lib/FAST/List/Gen/Lazy.pm view on Meta::CPAN
my $need;
if (@_) {
if (defined $_[0] and $_[0] =~ /^\d+$/) {
$need = shift;
} else {
$proto = shift || '@';
}
}
my $returns = @_ ? shift : $will_return{$code} || 1;
my ($head) = $proto =~ /^([^;]*)(?:;.*)?$/
or carp "unsupported prototype: $proto";
unless (defined $need) {
$need = (()= $head =~ /$proto_chunk/go);
}
if ($need > 1 and $proto eq '@') {
$proto = ('@' x $need)
}
(my $next_proto = $proto) =~ s/^$proto_chunk//o;
my $self;
$self = my $ret = $set_proto->($proto, sub {
return $self unless @_;
my $args = \@_;
if (@_ < $need) {
&fn ($set_proto->($next_proto,
sub {$code->(@$args, @_)}
), $need - @_, $returns)
}
elsif (@_ >= $need) {
my $thunk = sub {$code->(@$args)};
my $data;
if ($returns == 1) {
bless \sub {
unless ($data) {
$data = \scalar $thunk->();
$data = \$$$data->() if ref $$data eq 'FAST::List::Gen::Thunk';
undef $thunk;
}
$$data
} => 'FAST::List::Gen::Thunk'
} else {
map {
my $n = $_ - 1;
bless \sub {
unless ($data) {
$data = sub {\@_}->(map {
ref eq 'FAST::List::Gen::Thunk' ? $$_->() : $_
} $thunk->());
undef $thunk;
}
$$data[$n]
} => 'FAST::List::Gen::Thunk'
} 1 .. $returns
}
}
});
Scalar::Util::weaken($self);
if ($returns > 1) {
$will_return{$ret} = $returns;
}
$ret
}
}
{package
FAST::List::Gen::Function;
use overload fallback => 1,
'.' => \&compose,
'~' => \&flip,
(map {$_ => \& curry} qw(< <<)),
(map {$_ => \&rcurry} qw(> >>));
my $wrap = do {
sub {
my $src_fn = shift;
unless (ref $src_fn eq 'FAST::List::Gen::Bare::Function') {
push @_, $will_return->($src_fn);
goto &$fn;
}
my ($code, $proto) = @_;
$proto ||= '@';
bless Scalar::Util::set_prototype(\&$code, $proto), 'FAST::List::Gen::Bare::Function';
}
};
sub compose {
my ($x, $y) = @_;
($x, $y) = ($y, $x) if $_[2];
$wrap->($x, sub {$x->(&$y)}, prototype $y)
}
sub curry {
my $x = shift;
my $y = \$_[0];
my $proto = prototype $x;
my $new_proto = $proto =~ /^\@(?!\@)/ ? $proto : $proto_tail->($proto);
$wrap->($x, sub {$x->($$y, @_)}, $new_proto);
}
sub rcurry {
my $x = shift;
my $y = \$_[0];
$wrap->($x, sub {$x->(@_, $$y)}, $proto_init->(prototype $x));
}
sub flip {
my $x = shift;
my ($head, $tail) = (prototype($x) || '@') =~ /^([^;]+)(.*)/;
my $new_proto = (join '' => reverse $proto_split->($head)).$tail;
$wrap->($x, sub {$x->(@_[reverse 0 .. $#_])}, $new_proto);
}
}
{package
FAST::List::Gen::Bare::Function;
our @ISA = 'FAST::List::Gen::Function';
}
( run in 1.755 second using v1.01-cache-2.11-cpan-140bd7fdf52 )