Skip to content

Commit

Permalink
Implement Any.reduce in Perl 6, bacek++, pmichaud++
Browse files Browse the repository at this point in the history
  • Loading branch information
moritz committed Mar 10, 2009
1 parent d8f59ef commit 0c893bc
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 64 deletions.
62 changes: 0 additions & 62 deletions src/builtins/any-list.pir
Expand Up @@ -296,68 +296,6 @@ Return a List with the keys of the invocant.
.tailcall self.'pick'($I0)
.end

=item reduce(...)

=cut

.namespace []
.sub 'reduce' :multi('Sub')
.param pmc expression
.param pmc values :slurpy
.tailcall values.'reduce'(expression)
.end

.namespace ['Any']
.sub 'reduce' :method :multi(_, 'Sub')
.param pmc expression
.local pmc retv
.local pmc iter
.local pmc elem
.local pmc args
.local int i, arity

arity = expression.'arity'()
if arity < 2 goto error

iter = self.'iterator'()
unless iter goto empty
retv = shift iter
loop:
unless iter goto done

# Create arguments for closure
args = new 'ResizablePMCArray'
# Start with 1. First argument is result of previous call
i = 1

args_loop:
if i == arity goto invoke
unless iter goto elem_undef
elem = shift iter
goto push_elem
elem_undef:
elem = 'undef'()

push_elem:
push args, elem
inc i
goto args_loop

invoke:
retv = expression(retv, args :flat)
goto loop

empty:
.tailcall '!FAIL'('Cannot reduce an empty list')

error:
'die'('Cannot reduce() using a unary or nullary function.')

done:
.return(retv)
.end


=item sort()

Sort list. In this case we copy into an FPA to make use of the
Expand Down
35 changes: 33 additions & 2 deletions src/setting/Any-list.pm
Expand Up @@ -46,6 +46,33 @@ class Any is also {
}
}
}

multi method reduce( Code $expression is rw) {
my Int $arity = $expression.count;
fail('Cannot reduce() using a unary or nullary function.')
if $arity < 2;

my $l := @.list;

fail('Cannot reduce() empty list') unless +$l;

my @args;
for $l {
@args.push($_);
if (@args == $arity) {
my $res = $expression.(|@args);
@args = ($res);
}
}
if @args > 1 {
if @args < $expression.arity {
warn (@args -1) ~ " trailing item(s) in reduce";
} else {
return $( $expression.(|@args) );
}
}
return @args[0];
}
}

our List multi grep(Code $test, *@values) {
Expand All @@ -56,12 +83,16 @@ our List multi map(Code $expr, *@values) {
@values.map($expr)
}

multi min(Code $by, *@values) {
@values.min($by);
}

our List multi pairs(@values, *@indices) {
@values.pairs(@indices)
}

multi min(Code $by, *@values) {
@values.min($by);
multi reduce(Code $expression, *@values) {
@values.reduce($expression);
}

# vim: ft=perl6

0 comments on commit 0c893bc

Please sign in to comment.