Perl

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • Lazy lists in Str context

    10 answers - 354 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    Can we have:
    say 1Inf;
    to output an infinite stream, instead of just looping forever?
    TH, it would be nice if
    say substr( ~(1Inf), 0, 10 )
    printed "1 2 3 4 5".
    Flattened lists would still loop forever (or fail):
    say **(1Inf);
    $s = substr( ~( **(1Inf) ), 0, 10 );
    - Flavio S. Glock
  • No.1 | | 633 bytes | |

    11/23/05, Flavio S. Glock <fglock (AT) gmail (DOT) comwrote:
    Can we have:

    say 1Inf;

    to output an infinite stream, instead of just looping forever?

    TH, it would be nice if

    say substr( ~(1Inf), 0, 10 )

    printed "1 2 3 4 5".

    Flattened lists would still loop forever (or fail):

    say **(1Inf);

    $s = substr( ~( **(1Inf) ), 0, 10 );

    This would work, I think, if ranges were convertable to iterators,
    stringification was lazy, and substr() informed the stringification of
    how much it needed to do. I'm not sure how feasible that last one is

    Rob
  • No.2 | | 1127 bytes | |

    Flavio S. Glock skribis 2005-11-23 10:13 (-0200):
    Can we have:
    say 1Inf;

    It's important, I think, to note that this isn't item context, but list
    context. Str list context, but still list context. Which means 1Inf
    isn't stringified as a whole. &say will have an array that represents
    the lazy list. It should iterate over that rather than output it all at
    once, anyway, for reasons of conserving memory.

    to output an infinite stream, instead of just looping forever?

    How do you imagine anything outputs infinite stuff, without looping
    forever? I don't think stdout knows about our kind of laziness :)

    TH, it would be nice if
    say substr( ~(1Inf), 0, 10 )
    printed "1 2 3 4 5".

    Here, 1Inf is stringified as a whole, while with say, each of the
    individual elements of the list are separately stringified. The question
    of lazy strings is an interesting one. It would be very useful, and
    would also allow GREAT things like

    my $revfoo := reverse $foo;
    $revfoo ~~ s/foo/bar/g;

    I wonder if it's doable, though

    Juerd
  • No.3 | | 1125 bytes | |

    Wed, Nov 23, 2005 at 12:07:08PM -0500, Rob Kinyon wrote:
    : 11/23/05, Flavio S. Glock <fglock (AT) gmail (DOT) comwrote:
    : TH, it would be nice if
    : >
    : say substr( ~(1Inf), 0, 10 )
    : >
    : printed "1 2 3 4 5".

    : This would work, I think, if ranges were convertable to iterators,

    Range objects are supposed to *be* iterators, but pugs isn't there yet,
    last I checked.

    : stringification was lazy, and substr() informed the stringification of
    : how much it needed to do. I'm not sure how feasible that last one is
    :

    I think the last one is more feasible than the middle one, at least
    by default. The problem is that stringification is considered a result
    of a kind of scalar context, and ordinary scalar context is not lazy
    in Perl 6. So we'd probably need to set up some way of declaring
    "this particular string is lazy".

    Basically, we're attaching the whole lazy/nonlazy mess to the
    list/scalar distincion, which I think is a really good default.
    We use ** and lazy() to violate those defaults.

    Larry
  • No.4 | | 1709 bytes | |

    Juerd:

    2005/11/23, Juerd <juerd (AT) convolution (DOT) nl>:
    Flavio S. Glock skribis 2005-11-23 10:13 (-0200):
    Can we have:
    say 1Inf;

    It's important, I think, to note that this isn't item context, but list
    context. Str list context, but still list context. Which means 1Inf
    isn't stringified as a whole. &say will have an array that represents
    the lazy list. It should iterate over that rather than output it all at
    once, anyway, for reasons of conserving memory.

    Ah, ok - but I believe that say() is slurpy, which means the list must
    be instantiated first.

    to output an infinite stream, instead of just looping forever?

    How do you imagine anything outputs infinite stuff, without looping
    forever? I don't think stdout knows about our kind of laziness :)

    There are some reasons for this - you can see what's happening, and
    press ctrl-C; or you may wish for it to output until there is a
    timeout; or maybe you are writing a daemon which is supposed to run
    forever anyway.

    TH, it would be nice if
    say substr( ~(1Inf), 0, 10 )
    printed "1 2 3 4 5".

    Here, 1Inf is stringified as a whole, while with say, each of the
    individual elements of the list are separately stringified. The question
    of lazy strings is an interesting one. It would be very useful, and
    would also allow GREAT things like

    my $revfoo := reverse $foo;
    $revfoo ~~ s/foo/bar/g;

    I wonder if it's doable, though

    I believe it is - I've come to this idea while trying to write down
    the Array spec, and it seems pretty feasible.

    Juerd

    Thanks!
    - Flavio
  • No.5 | | 451 bytes | |

    Larry Wall skribis 2005-11-23 11:16 (-0800):
    Range objects are supposed to *be* iterators, but pugs isn't there yet,
    last I checked.

    Is the associated sigil @ or $? Either way, there's a problem. $foo
    can't flatten in list context, which does want, which would be
    inconsistent, but with @, it cannot be copied, because that flattens in
    list context, which is provided by assignment to another @-thing.

    Juerd
  • No.6 | | 776 bytes | |

    Wed, Nov 23, 2005 at 05:24:11PM -0200, Flavio S. Glock wrote:
    : Ah, ok - but I believe that say() is slurpy, which means the list must
    : be instantiated first.

    It's * instantiated, but not ** instantiated, so the iterators buried
    in the .specs of the list aren't forced to evaluate yet. And ranges
    are iterator objects. The hidden iterators of a * list are evaluated
    when the values are requested from the slurpy array. So

    say 1;

    ought to produce lots of output without ever running out of memory.

    (In reality, iterators are allowed to produce their values in batches
    for efficiency, so there's a slight possibility that an iterator
    could exhaust memory while producing the next batch.)

    Larry
  • No.7 | | 1170 bytes | |

    Wed, Nov 23, 2005 at 08:35:09PM +0100, Juerd wrote:
    : Larry Wall skribis 2005-11-23 11:16 (-0800):
    : Range objects are supposed to *be* iterators, but pugs isn't there yet,
    : last I checked.
    :
    : Is the associated sigil @ or $? Either way, there's a problem.

    No, either way it does what you want.

    : $foo can't flatten in list context, which does want, which would be
    : inconsistent,

    If you say

    $r = 110;

    you are intentionally putting the range object in a place where you
    have to explicitly iterate it, so in list context you'd have to say

    for =$r { say }

    : but with @, it cannot be copied, because that flattens in
    : list context, which is provided by assignment to another @-thing.

    It only flattens notionally as * lazy, which means if you say

    @r = 110;
    @s = @r;

    the iterator doesn't have to be evaluated, but just passed along as
    part of the .specs to the next array, presumably with CW so the two
    arrays can then have the appearance of having flattened the iterator.
    But it's all * magic, not ** magic.

    Larry
  • No.8 | | 923 bytes | |

    2005/11/23, Larry Wall <larry (AT) wall (DOT) org>:

    I think the last one is more feasible than the middle one, at least
    by default. The problem is that stringification is considered a result
    of a kind of scalar context, and ordinary scalar context is not lazy
    in Perl 6. So we'd probably need to set up some way of declaring
    "this particular string is lazy".

    Basically, we're attaching the whole lazy/nonlazy mess to the
    list/scalar distincion, which I think is a really good default.
    We use ** and lazy() to violate those defaults.

    How about allowing reduce() to return a scalar with the same laziness
    as the list:

    [~]@list - a lazy string if @list is lazy[*]@list - a lazy number if @list is lazy

    It would look like:

    $foo = substr( [~](1Inf), 10 );
    my $revfoo := reverse $foo;
    $revfoo ~~ s/foo/bar/g;
    - Flavio S. Glock
  • No.9 | | 911 bytes | |

    11/23/05, Flavio S. Glock <fglock (AT) gmail (DOT) comwrote:
    How about allowing reduce() to return a scalar with the same laziness
    as the list:

    [~]@list - a lazy string if @list is lazy[*]@list - a lazy number if @list is lazy

    It would look like:

    $foo = substr( [~](1Inf), 10 );
    my $revfoo := reverse $foo;
    $revfoo ~~ s/foo/bar/g;

    That would violate the principle of least surprise. If all scalars
    are, by default, eager, then:

    foo( [~]@list );
    foo( @list.join('') );

    could potentially do different things, including possibly run out of
    memory in some cases. Plus, what if the @list isn't lazy?

    Better, I think, would be:

    say substr( ~(1Inf) is lazy, 0, 10 );

    , have substr()'s signature be:

    sub substr( Str $str is rw is lazy, Int $start, Int $?end, Int $?replacement );

    Rob
  • No.10 | | 1176 bytes | |

    11/23/05, Larry Wall <larry (AT) wall (DOT) orgwrote:
    Basically, we're attaching the whole lazy/nonlazy mess to the
    list/scalar distincion, which I think is a really good default.
    We use ** and lazy() to violate those defaults.

    I think you might be mixing up the "scope" of laziness here. Having a
    lazy string to me is much like:

    my @a = 1;
    my $b = \@a;

    Scalar context is strict, but that doesn't necessitate strict
    evaluation the whole way down. The scalar context in that example is
    saying "evaluate the reference *now*", not the list.

    The kind of lazy string that would be affected by scalar context is:

    my $str = do { say "hi there"; "foo" };
    say "intermediate";
    say $str;

    If scalar context were lazy, it would say "hi there" *after*
    "intermediate" (but before "foo", of course).

    But we're talking about a string with a lazy internal representation,
    like a reference to a lazy list. That's perfectly okay to pass around
    in scalar context. And I think it's perfectly okay to have
    stringification return this kind of lazy string.

    Luke

Re: Lazy lists in Str context


max 4000 letters.
Your nickname that display:
In order to stop the spam: 7 + 7 =
QUESTION ON "Perl"

EMSDN.COM