Re: Lazy lists in Str context

2005-11-23 Thread Luke Palmer
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

2005-11-23 Thread Rob Kinyon
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 Thread Flavio S. Glock
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

2005-11-23 Thread Larry Wall
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

2005-11-23 Thread Larry Wall
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

2005-11-23 Thread Juerd
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

2005-11-23 Thread Flavio S. Glock
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

2005-11-23 Thread Larry Wall
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

2005-11-23 Thread Juerd
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

2005-11-23 Thread Rob Kinyon
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

2005-11-23 Thread Flavio S. Glock
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