On Tue, May 01, 2012 at 09:11:22AM -0700, Carl Mäsak wrote:
> <tadzik> r: for $*IN.lines -> $line { say $line.lc }
> <p6eval> rakudo 4c241c: OUTPUT«land der berge, land am strome, [...]
> <goraki> tadzik: masak: when I run either I don't get any output until
> I hit ctrl-d to "end" the input.
> <masak> goraki: let my try locally.
> <masak> my gosh, you're right!
> * masak submits rakudobug
> [...]
> <masak> lines() is supposed to be lazy.

Actually, as implemented lines() is already "lazy":

    pmichaud@kiwi:~/p6/rakudo$ ./perl6
    > my @a := $*IN.lines().map( { .lc.say } ); 1;
    1
    > say @a[0]
    HELLO
    hello
    True
    >

The problem is actually in the .map code itself (I suspect
a misoptimization) -- when map is attempting to reify multiple
elements, it's batching up the required number of elements
before processing any of them:

    > @a[3]
    WORLD
    GOODBYE
    WORLD
    world
    goodbye
    world
    > 

The problem line is in src/core/MapIter.pm:

    my $munched := $!list.munch($argc * $count);

This causes all of the requested elements of the source $!list to
be reified before any of them are processed, thus .map isn't
properly lazy.  This line was added as an optimization to make
some .map operations faster, but lost some of the lazy aspects
of map (as well as other things).

The correct approach is to make .munch sufficiently performant
over repeated calls (avoiding repeated shifts of the
underlying list structures), which I plan to take care of 
shortly.

Pm

Reply via email to