in reply to Re: Concise foreach expression
in thread Concise foreach expression

which means you won't have much use of nested loops with map

Could you explain what you mean there? map localizes $_, so nested maps are not a problem. Code like the following (admittedly contrived) snippet works as expected ($_ is not clobbered by the inner map):

my @list = ( ["Barney", "Rubble"], ["Fred", "Flintstone"], ["Betty", "Rubble"], ["Wilma", "Flintstone"] ); map { say "Outer map before: @$_"; map { 1 } @$_; say "Outer map after : @$_"; } @list;

But perhaps there's other pitfalls, so I'd be grateful for any enlightenment.

Replies are listed 'Best First'.
Re^3: Concise foreach expression
by choroba (Cardinal) on Aug 29, 2014 at 17:14 UTC
    The problem happens when you need to use the $_ from the outer map in the inner map, as in the following contrived example:
    my %tree = ( child1 => {}, child2 => { grandchild1 => { brood3 => {} }, grandchild2 => { brood1 => {}, brood2 => {} }, }, ); say for 'Grandchildren:', map { my $x = $_; # <--- remove me! "$_: " . (ref $tree{$_} ? join ', ' => map keys %{ $tree{$x}{$_} }, keys %{ $tree{$_} } : q()) } keys %tree;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re^3: Concise foreach expression
by LanX (Saint) on Aug 29, 2014 at 17:00 UTC
    > Could you explain what you mean there?

    I was talking about chaining maps or fors to simulate nested foreach loops.

    I.o.w. list comprehensions are very hard to implement in Perl without nested blocks.

    e.g. try to implement this Python example for "Pythagorean triples" w/o nesting

    >>> [(x,y,z) for x in range(1,30) for y in range(x,30) for z in range( +y,30) if x**2 + y**2 == z**2] [(3, 4, 5), (5, 12, 13), (6, 8, 10), (7, 24, 25), (8, 15, 17), (9, 12, + 15), (10, 24, 26), (12, 16, 20), (15, 20, 25), (20, 21, 29)]

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

      Ah, yes, I see what you mean.
        FWIW

        I once implemented a ( Monad style ;-) approach to emulate this

         @results = take { [$a,$b,$c] if $a**2 +$b**2 ==$c**2 } from {1..30} $a from {1..$a} $b from {1...$b} $c

        take(&$) and from(&$$) where just ordinary functions passing iterators around.

        The problem I couldn't solve was a DRY scoping of the variables, to be strict I needed to surround the whole expression with

        { my($a,$b,$c); ... }

        my declarations don't effect the scope of the same line. :(

        Cheers Rolf

        (addicted to the Perl Programming Language and ☆☆☆☆ :)

        update

        hmm maybe this syntax is acceptable?

        from { 1..30} my $a from {1..$a} my $b from { 1...$b} my $c; @results = take { [$a,$b,$c] if $a**2 +$b**2 ==$c**2 }

        when called from void context from() could put the iterator into $_ , and take() could read it again from $_ if called with just one block arg...

        never mind doesn't work.