in reply to Re: Summing the elements of multiple arrays into a new array
in thread Summing the elements of multiple arrays into a new array

  use 6; # require perl v6
  use List::Util qw/reduce/;

  @foobar = @{reduce{@$a ^+ @$b}\(@foo, @bar, @baz, @etc)};

reduce will almost certainly be a built-in in Perl 6, so you won't need to use List::Util.

That hideously lovely third line certainly would do the job in Perl 6 (well done!), but was it really necessary to be so cruel to the mere mortals who'll have to maintain that code???

kwoff is perfectly correct -- in Perl 6 you'll just need:

	@foobar = @foo ^+ @bar ^+ @baz ^+ @etc;
or possibly even:
	@foobar = ^sum(@foo,@bar,@baz,@etc);
BTW, all of the above code has been tested. ;-)
  • Comment on Re: Re: Summing the elements of multiple arrays into a new array

Replies are listed 'Best First'.
Re: Re: Re: Summing the elements of multiple arrays into a new array
by Sidhekin (Priest) on Nov 01, 2001 at 16:52 UTC

    That hideously lovely third line certainly would do the job in Perl 6 (well done!), but was it really necessary to be so cruel to the mere mortals who'll have to maintain that code???

    Of course not -- that was just sillyness :-)

    What I really wanted was to show off reduce. And so, I am very happy to hear that reduce will (almost certainly) be a built-in in Perl 6. For my next hope-to-see, that reduce will DWIM with lists (still silly, since "^+" is as easy as ",", but in this context, that is just an example, okay):

    # I hope this works: @foobar = reduce {@a ^+ @b} @foo, @bar, @baz, @etc; # ... or this: @foobar = reduce {@$a ^+ @$b} @foo, @bar, @baz, @etc; # ... or possibly this: @foobar = reduce {$a ^+ $b} @foo, @bar, @baz, @etc;

    Unless there is one flattening and one non-flattening reduce (which sounds like a waste), that would mean that to apply reduce to the flattened list, you would need to explicitly flatten it, right?

    @foobar = reduce {$a + $b} *(@foo, @bar, $baz, $etc);

    Looks weird, but I could live with it :-)
    {... daydreams of Perl 6 ...}

    The Sidhekin
    print "Just another Perl ${\(trickster and hacker)},"

      For my next hope-to-see, that reduce will DWIM with lists

      I don't think any of the syntaxes you suggested will be the way to do this, but it might be that reduce will honour the parameter contexts specified by its reduction block, so this would work:

      @foobar = reduce {[@^a ^+ @^b]} @foo, @bar, @baz, @etc;

      How? Well, the @^a and @^b make the reduction block a curried subroutine, whose parameter list consists of two unflattened arrays. That is:

      {[@^a ^+ @^b]}
      is shorthand for:
      sub (@a, @b) { return [@a ^+ @b] }
      (modulo the currying (which isn't used here (so forget I mentioned it))).

      With that parameter list on its reduction block, reduce would expect arrays instead of scalars as its remaining arguments.

      Note that the square brackets are critical here, since reduce always applies the reduction in scalar context, but we need to get back something that can be treated like an array in the next reduction (i.e. an array reference).

      That is: the result of the first reduction step has to be a scalar, but that result -- when it becomes the first argument to the reduction block in the second step of the reduction -- has to be an array. Perl 6's auto-intra-conversion of arrays and array refs makes that possible.

      Having reduce and other list ops honour their block's parameter list would be very cool in other ways too:

      # sum of maximal values... $maxsum = reduce { $^a + max(@^b) } 0, @foo, @bar, @etc;

      In this example the reduction block has two parameters: a scalar and an unflattened array. So it sucks corresponding elements from the argument list (i.e. 0 and @foo), finds the maximum value in @foo, and adds it to the partial sum. The result becomes the first argument of the next reduction step, which then grabs @bar for its second argument, finds @bar's maximum and adds it in. That result becomes the first argument to the third reduction, which grabs @etc, and adds its maximum as well. Having exhausted all its arguments, reduce returns the final reduction result, which turns out to be the sum of all maxima.

      Pushing the envelope a little, we could also write:

      # grep out hash entries whose key *or* value is 'moo'... %cow = map { any($^key,$^val) eq 'moo' ?? $^key => $^val :: () } % +animals;

      Here, the mapping block is equivalent to:

      sub ($key, $val) { ... }
      So each mapping step would pull two scalar arguments off the map's argument list. If either is 'moo', the block returns the pair; otherwise it returns an empty list (which is flattened out of existence in the resultant list). The outcome is that the %cow hash is assigned a list of pairs, which become its entries.

      Where to the scalar keys and values come from? They're flattened out of the %animals hash by the scalar contexts imposed by the two scalar arguments of the reduction block (!)

      BTW, that map { $test ? $result : () } @data construct is a trick you can use in Perl 5 too. It's the infamous "grepping map" (i.e. a floor wax and a dessert topping).

      Update: Fixed the missing second colon on the ternary operator in the last example. Thanks blakem!

        I like it, I like it. ++

        If I understand correctly this implicit parameter stuff, I guess I'll be able to do stuff like this:

        sub operator:mat* is prec(\&operator:*) (@X, @Y) { return map { $^m1; # disambiguate ... right? reduce{[ @^a ^+ @^b ]} map { $X[$^m1][$^m2] ^* @{$Y[$^m2]} } 0 .. $#Y } } 0 .. $#X; }
        {hoping I got the math right, at least}

        I guess if I had more opportunities to write Perl 5 programs ATM, I would do that instead, but these glimpses into the future sure brighten my day. (And next week, there will be Perl programming at work. Yay!)

        The Sidhekin
        print "Just another Perl ${\(trickster and hacker)},"

      Unless there is one flattening and one non-flattening reduce...

      There won't be.

      that would mean that to apply reduce to the flattened list, you would need to explicitly flatten it, right?

      Right.