Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: Re: Re: Re: Summing the elements of multiple arrays into a new array

by TheDamian (Vicar)
on Nov 02, 2001 at 02:30 UTC ( [id://122702]=note: print w/replies, xml ) Need Help??


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

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!

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

    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)},"

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://122702]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-19 17:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found