9

I'm trying to use map inside a for loop, but this code is not working. This code should print 1 and 2 three times. But the code below produces no output. It will only partially work if you uncomment the exit line. Any idea why? I tested it using the current Perl 6 version (Rakudo version 2015.12-79-g4bb47d5 built on MoarVM version 2015.12 and also the Windows version).

for (1..3) {
 map { say $_ }, (1..2);
# exit;
}
Christopher Bottoms
  • 11,218
  • 8
  • 50
  • 99

1 Answers1

8

Let's take a look at

say (map { say $_ }, 1..2).WHAT;

This tells us &map returns a Seq, which is a lazy construct.

Additionally, the last statement in the body of a for loop is used to aggregate its return value, cf

my @list = do for 1..3 {
    map { say $_ }, 1..2;
}

say .WHAT for @list;

If you add another statement after the call to &map, the call will be in 'sink context' and gets evaluated eagerly.

This can also be forced explicitly:

for 1..3 {
    sink map { say $_ }, 1..2;
}

Alternatively, just use another for loop:

for 1..3 {
    .say for 1..2;
}
Christoph
  • 164,997
  • 36
  • 182
  • 240
  • 1
    You can also force it to be an eager sequence by using `eager` instead of `sink`. Really `for` should just put all of its statements into `sink` context if it isn't preceded by a `do` ( `do for 1..3 { … }` ) – Brad Gilbert Jan 12 '16 at 00:53
  • 5
    Seems the lesson here is: be careful about using a filter function like map for side effects as if it's a loop. – Aaron Baugher Jan 12 '16 at 12:37