Re: Lazy lists in Str context
On 11/23/05, Larry Wall <[EMAIL PROTECTED]> wrote: > 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 = [EMAIL PROTECTED]; 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
On 11/23/05, Flavio S. Glock <[EMAIL PROTECTED]> wrote: > How about allowing reduce() to return a scalar with the same laziness > as the list: > > [EMAIL PROTECTED] - a lazy string if @list is lazy > [EMAIL PROTECTED] - a lazy number if @list is lazy > > It would look like: > > $foo = substr( [~](1..Inf), 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( [EMAIL PROTECTED] ); 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( ~(1..Inf) is lazy, 0, 10 ); Or, have substr()'s signature be: sub substr( Str $str is rw is lazy, Int $start, Int $?end, Int $?replacement ); Rob
Re: Lazy lists in Str context
2005/11/23, Larry Wall <[EMAIL PROTECTED]>: > > 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: [EMAIL PROTECTED] - a lazy string if @list is lazy [EMAIL PROTECTED] - a lazy number if @list is lazy It would look like: $foo = substr( [~](1..Inf), 10 ); my $revfoo := reverse $foo; $revfoo ~~ s/foo/bar/g; - Flavio S. Glock
Re: Lazy lists in Str context
On 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 = 1..10; 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 = 1..10; @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 COW so the two arrays can then have the appearance of having flattened the iterator. But it's all * magic, not ** magic. Larry
Re: Lazy lists in Str context
On 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
Re: Lazy lists in Str context
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 -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Lazy lists in Str context
Juerd: 2005/11/23, Juerd <[EMAIL PROTECTED]>: > Flavio S. Glock skribis 2005-11-23 10:13 (-0200): > > Can we have: > > say 1..Inf; > > 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 1..Inf > 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. > > OTOH, it would be nice if > > say substr( ~(1..Inf), 0, 10 ) > > printed "1 2 3 4 5". > > Here, 1..Inf 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
Re: Lazy lists in Str context
On Wed, Nov 23, 2005 at 12:07:08PM -0500, Rob Kinyon wrote: : On 11/23/05, Flavio S. Glock <[EMAIL PROTECTED]> wrote: : > OTOH, it would be nice if : > : > say substr( ~(1..Inf), 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
Re: Lazy lists in Str context
Flavio S. Glock skribis 2005-11-23 10:13 (-0200): > Can we have: > say 1..Inf; 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 1..Inf 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 :) > OTOH, it would be nice if > say substr( ~(1..Inf), 0, 10 ) > printed "1 2 3 4 5". Here, 1..Inf 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 -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Lazy lists in Str context
On 11/23/05, Flavio S. Glock <[EMAIL PROTECTED]> wrote: > Can we have: > > say 1..Inf; > > to output an infinite stream, instead of just looping forever? > > OTOH, it would be nice if > > say substr( ~(1..Inf), 0, 10 ) > > printed "1 2 3 4 5". > > Flattened lists would still loop forever (or fail): > > say **(1..Inf); > > $s = substr( ~( **(1..Inf) ), 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
Lazy lists in Str context
Can we have: say 1..Inf; to output an infinite stream, instead of just looping forever? OTOH, it would be nice if say substr( ~(1..Inf), 0, 10 ) printed "1 2 3 4 5". Flattened lists would still loop forever (or fail): say **(1..Inf); $s = substr( ~( **(1..Inf) ), 0, 10 ); - Flavio S. Glock