Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Continuations

37 views
Skip to first unread message

Luke Palmer

unread,
Nov 5, 2002, 11:52:56 AM11/5/02
to perl6-l...@perl.org
I just need a little clarification about yield().

consider this sub:

sub iterate(@foo) {
yield for @foo;
undef;
}

(Where yield defaults to the topic) Presumably.

@a = (1, 2, 3, 4, 5);
while($_ = iterate @a) {
print
}

Will print "12345". Or is that:

for @a {
print
}

? So, does yield() build a lazy array, or does it act like an eplicit
iterator? If the latter, how do you tell the difference between a
recursive call and fetching the next element? How would you maintain
two iterators into the same array?

Luke

Damian Conway

unread,
Nov 5, 2002, 6:38:45 PM11/5/02
to perl6-l...@perl.org
Luke Palmer wrote:

> I just need a little clarification about yield().

The first point of clarification is that the subject is a little off.
C<yield> gives us *co-routines*, not *continuations*.


> consider this sub:
>
> sub iterate(@foo) {
> yield for @foo;
> undef;
> }
>
> (Where yield defaults to the topic) Presumably.

I'm not so sure. C<return> doesn't default to topic; C<yield> probably
shouldn't either.


> @a = (1, 2, 3, 4, 5);
> while($_ = iterate @a) {
> print
> }
>
> Will print "12345".

Yes.


> So, does yield() build a lazy array, or does it act like an eplicit
> iterator?

The latter. C<yield> is exactly like a C<return>, except that when you
call the subroutine next time, it resumes from after the C<yield>.


> If the latter, how do you tell the difference between a
> recursive call and fetching the next element? How would you maintain
> two iterators into the same array?

The re-entry point isn't stored in the subroutine itself. It's stored
(indexed by optree node) in the current subroutine call frame. Which,
of course, is preserved when recursive iterator invocations recursively
yield.

Damian

Peter Haworth

unread,
Nov 12, 2002, 9:30:24 AM11/12/02
to Damian Conway, perl6-l...@perl.org
On Wed, 06 Nov 2002 10:38:45 +1100, Damian Conway wrote:
> Luke Palmer wrote:
> > I just need a little clarification about yield().
>
> C<yield> is exactly like a C<return>, except that when you
> call the subroutine next time, it resumes from after the C<yield>.
>
> > how do you tell the difference between a
> > recursive call and fetching the next element? How would you maintain
> > two iterators into the same array?
>
> The re-entry point isn't stored in the subroutine itself. It's stored
> (indexed by optree node) in the current subroutine call frame. Which,
> of course, is preserved when recursive iterator invocations recursively
> yield.

So to get the same yield context, each call to the coroutine has to be from
the same calling frame. If you want to get several values from the same
coroutine, but from different calling contexts, can you avoid the need to
wrap it in a closure?

sub iterate(@foo){
yield $_ for @foo;
undef;
}

# There's probably some perl5/6 confusion here
sub consume(@bar){
my $next = sub{ iterate(@bar); };
while $_ = $next() {
do_stuff($_,$next);
}
}

sub do_stuff($val,$next){
...
if $val ~~ something_or_other() {
my $quux = $next();
...
}
}


--
Peter Haworth p...@edison.ioppublishing.com
"...I find myself wondering if Larry Ellison and Tim Curry
were separated at birth...hmm..."
-- Tom Good

Peter Haworth

unread,
Nov 13, 2002, 9:13:10 AM11/13/02
to Damian Conway, perl6-l...@perl.org
On Tue, 12 Nov 2002 14:30:24 +0000, Peter Haworth wrote:
> So to get the same yield context, each call to the coroutine has to be from
> the same calling frame. If you want to get several values from the same
> coroutine, but from different calling contexts, can you avoid the need to
> wrap it in a closure?

I'm an idiot. Why not make the closure a coroutine itself?

sub consume(@bar){
my $next=sub{ yielf $_ for @bar; return; };
while my $val = $next() {
do_stuff($val,$next);
}
}

> sub do_stuff($val,$next){
> ...
> if $val ~~ something_or_other() {
> my $quux = $next();
> ...
> }
> }
>

--
Peter Haworth p...@edison.ioppublishing.com
"The term `Internet' has the meaning given that term in
section 230(f)(1) of the Communications Act of 1934."
-- H.R. 3028, Trademark Cyberpiracy Prevention Act

Damian Conway

unread,
Nov 16, 2002, 4:31:02 PM11/16/02
to perl6-l...@perl.org
Peter Haworth asked:

> So to get the same yield context, each call to the coroutine has to be from
> the same calling frame. If you want to get several values from the same
> coroutine, but from different calling contexts, can you avoid the need to
> wrap it in a closure?

I don't think so.

Damian

Dan Sugalski

unread,
Nov 16, 2002, 7:06:52 PM11/16/02
to perl6-l...@perl.org

I dunno. One of the things I've seen with coroutines is that as long
as you call them with no arguments, you get another iteration of the
coroutine--you actually had to call it with new arguments to reset
the thing. (Which begs the question of what you do when you have a
coroutine that doesn't take any args, but that's a separate issue)

OTOH, forcing a closure allows you to have multiple versions of the
same coroutine instantiated simultaneously, which strikes me as a
terribly useful thing.

Perhaps we'd be better with an explicit coroutine instantiation call, like:

$foo = &bar.instantiate(1, 2, 3);

or something. (Or not, as it is ugly)
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Damian Conway

unread,
Nov 16, 2002, 9:29:31 PM11/16/02
to perl6-l...@perl.org
Dan Sugalski wrote:

> I dunno. One of the things I've seen with coroutines is that as long as
> you call them with no arguments, you get another iteration of the
> coroutine--you actually had to call it with new arguments to reset the
> thing.

The formulation of coroutines I favour doesn't work like that.

Every time you call a suspended coroutine it resumes from immediately
after the previous C<yield> than suspended it. *And* that C<yield>
returns the new argument list with which it was resumed.

So you can write things like:

sub pick_no_repeats (*@from_list) {
my $seen;
while (pop @from_list) {
next when $seen;
@from_list := yield $_;
$seen |= $_;
}
}

# and later:

while pick_no_repeats( @values ) {
push @values, some_calc($_);
}

Allowing the list of choices to change, but repetitions still to be avoided.


> OTOH, forcing a closure allows you to have multiple versions of the same
> coroutine instantiated simultaneously, which strikes me as a terribly
> useful thing.

Yep!


> Perhaps we'd be better with an explicit coroutine instantiation call, like:
>
> $foo = &bar.instantiate(1, 2, 3);
>
> or something.

Ew!


(Or not, as it is ugly)

That'd be my vote! ;-)


Damian

Angel Faus

unread,
Nov 17, 2002, 7:00:21 AM11/17/02
to Damian Conway, perl6-l...@perl.org
Damian Conway wrote:
>
> The formulation of coroutines I favour doesn't work like that.
>
> Every time you call a suspended coroutine it resumes from immediately
> after the previous C<yield> than suspended it. *And* that C<yield>
> returns the new argument list with which it was resumed.
>
> So you can write things like:
>
> sub pick_no_repeats (*@from_list) {
> my $seen;
> while (pop @from_list) {
> next when $seen;
> @from_list := yield $_;
> $seen |= $_;
> }
> }
>
> # and later:
>
> while pick_no_repeats( @values ) {
> push @values, some_calc($_);
> }
>
> Allowing the list of choices to change, but repetitions still to be
avoided.
>

I understand that this formulation is more powefull, but one thing I like
about python's way (where a coroutine is just a funny way to generate lazy
arrays) is that it lets you _use_ coroutines without even knowing what they
are about.

Such as when you say:

for $graph.nodes { ... }

..nodes may be implemented as a coroutine, but you just don't care about it.
Plus any function that previously returned an array can be reimplemented as
coroutine at any time, without having to change the caller side.

In other words, how do you create a lazy array of dynamically generated
values in perl6?

Maybe it could be something like this:

$foo = &bar.instantiate(1, 2, 3);

@array = $foo.as_array;

-angel


Dan Sugalski

unread,
Nov 17, 2002, 12:57:42 PM11/17/02
to perl6-l...@perl.org
At 1:29 PM +1100 11/17/02, Damian Conway wrote:
>The formulation of coroutines I favour doesn't work like that.
>
>Every time you call a suspended coroutine it resumes from immediately
>after the previous C<yield> than suspended it. *And* that C<yield>
>returns the new argument list with which it was resumed.

Hrm. I can see the power, but there's a fair amount of internal
complication there. I'll have to ponder that one a bit to see if
there's something I'm missing that makes it easier than I think.

Damian Conway

unread,
Nov 17, 2002, 4:44:52 PM11/17/02
to perl6-l...@perl.org
Angel Faus wrote:

> I understand that this formulation is more powefull, but one thing I like
> about python's way (where a coroutine is just a funny way to generate lazy
> arrays) is that it lets you _use_ coroutines without even knowing what they
> are about.
>
> Such as when you say:
>
> for $graph.nodes { ... }
>
> .nodes may be implemented as a coroutine, but you just don't care about it.
> Plus any function that previously returned an array can be reimplemented as
> coroutine at any time, without having to change the caller side.

Yes, it may be that Pythonic -- as opposed to Satherian/CLUic -- iterators are
a better fit for Perl 6. It rather depends on the semantics of Perl 6
iterators, which Larry hasn't promulgated fully yet.


> In other words, how do you create a lazy array of dynamically generated
> values in perl6?
>
> Maybe it could be something like this:
>
> $foo = &bar.instantiate(1, 2, 3);
> @array = $foo.as_array;

Well, I think it has to be much less ugly than that! ;-)


Damian

Damian Conway

unread,
Nov 17, 2002, 5:28:59 PM11/17/02
to perl6-l...@perl.org
Of course, apart from the "call-with-new-args" behaviour, having
Pythonic coroutines isn't noticably less powerful. Given:

sub fibs ($a = 0 is copy, $b = 1 is copy) {
loop {
yield $b;
($a, $b) = ($b, $a+b);
}
}

we still have implicit iteration:

for fibs() {
print "Now $_ rabbits\n";
}

and explicit iteration:

my $iter = fibs();
while <$iter> {
print "Now $_ rabbits\n";
}

and explicit multiple iteration:

my $rabbits = fibs(3,5);
my $foxes = fibs(0,1);
loop {
my $r = <$rabbits>;
my $f = <$foxes>;
print "Now $r rabbits and $f foxes\n";
}

and even explicitly OO iteration:

my $iter = fibs();
while $iter.next {
print "Now $_ rabbits\n";
}


And there's no reason that a coroutine couldn't produce an iterator object
with *two* (overloaded) C<next> methods, one of which took no arguments
(as in the above examples), and one of which had the same parameter list
as the coroutine, and which rebound the original parameters on the next
iteration.

For example, instead of the semantics I proposed previously:

# Old proposal...

sub pick_no_repeats (*@from_list) {
my $seen;
while (pop @from_list) {
next when $seen;
@from_list := yield $_;
$seen |= $_;
}
}

# and later:

while pick_no_repeats( @values ) {
push @values, some_calc($_);
}


we could just write:

# New proposal

sub pick_no_repeats (*@from_list) {
my $seen;
while (pop @from_list) {
next when $seen;

yield $_;
$seen |= $_;
}
}

# and later:

my $pick = pick_no_repeats( @values );
while $pick.next(@values) {
push @values, some_calc($_);
}


These semantics also rather neatly solve the problem of whether or
not to re-evaluate/re-bind the parameters each time a coroutine
is resumed. The rule becomes simple: if the iterator's C<next>
method is invoked without arguments, use the old parameters;
if it's invoked with arguments, rebind the parameters.

And the use of the <$foo> operator to mean $foo.next cleans up
teh syntax nicely.

I must say I rather like this formulation. :-)

Damian

Luke Palmer

unread,
Nov 17, 2002, 6:15:12 PM11/17/02
to dam...@conway.org, perl6-l...@perl.org
> Date: Mon, 18 Nov 2002 09:28:59 +1100
> From: Damian Conway <dam...@conway.org>

I've a couple of questions here:

> we still have implicit iteration:
>
> for fibs() {
> print "Now $_ rabbits\n";
> }

Really? What if fibs() is a coroutine that returns lists (Fibonacci
lists, no less), and you just want to iterate over one of them? The
syntax:

for &fibs {


print "Now $_ rabbits\n";
}

Would make more sense to me for implicit iteration. Perhaps I'm not
looking at it right. How could you get the semantics of iterating
over just one list of the coroutine?

> and explicit iteration:
>
> my $iter = fibs();
> while <$iter> {
> print "Now $_ rabbits\n";
> }

Ahh, so $iter is basically a structure that has a continuation and a
value. When you call the .next method, it calls the continuation, and
delegates to the value otherwise. Slick (Unless the coroutine itself
is returning iterators... then... what?).

class Foo {
method next { print "Gliddy glub gloopy\n" }
}
sub goof () {
loop {
print "Nibby nabby nooby\n";
yield new Foo;
}
}

my $iter = goof;
print $iter.next; # No.. no! Gliddy! Not Nibby!

How does this work, then?

> For example, instead of the semantics I proposed previously:
>
> # Old proposal...
>
> sub pick_no_repeats (*@from_list) {
> my $seen;
> while (pop @from_list) {
> next when $seen;
> @from_list := yield $_;
> $seen |= $_;
> }
> }

Hang on... is C<while> a topicalizer now? Otherwise this code is not
making sense to me.

> These semantics also rather neatly solve the problem of whether or
> not to re-evaluate/re-bind the parameters each time a coroutine
> is resumed. The rule becomes simple: if the iterator's C<next>
> method is invoked without arguments, use the old parameters;
> if it's invoked with arguments, rebind the parameters.
>
> And the use of the <$foo> operator to mean $foo.next cleans up
> teh syntax nicely.

So filehandles are just loops that read lines constantly and yield
them. I'm really starting to like teh concept of tohse co-routines :)
They elegantify stuff.

Luke

Damian Conway

unread,
Nov 17, 2002, 8:35:56 PM11/17/02
to perl6-l...@perl.org
Luke Palmer enquired:

>>we still have implicit iteration:
>>
>> for fibs() {
>> print "Now $_ rabbits\n";
>> }
>
> Really? What if fibs() is a coroutine that returns lists (Fibonacci
> lists, no less), and you just want to iterate over one of them? The
> syntax:
>
> for &fibs {
> print "Now $_ rabbits\n";
> }
>
> Would make more sense to me for implicit iteration. Perhaps I'm not
> looking at it right. How could you get the semantics of iterating
> over just one list of the coroutine?

The semantics of C<for> would simply be that if it is given an iterator
object (rather than a list or array), then it calls that object's iterator
once per loop.


>>and explicit iteration:
>>
>> my $iter = fibs();
>> while <$iter> {
>> print "Now $_ rabbits\n";
>> }
>
>
> Ahh, so $iter is basically a structure

It's an object.


> that has a continuation and a
> value. When you call the .next method, it calls the continuation, and
> delegates to the value otherwise.

Err. No. Not quite. Though that would be cute too.


> (Unless the coroutine itself is returning iterators...

Yep.

The idea is that, when any subroutine (&f) with a C<yield> in it is called,
it immediately returns an Iterator object (i.e. without executing its body at
all). That Iterator object has (at least) two C<next> methods:

method next() {...}
method next(...) {...}

where the second C<next>'s parameter list is identical to the
parameter list of the original &f.

Code can then call the iterator's C<next> method, either explicitly:

$iter.next(...);

or operationally:

<$iter>

or implicitly (in a C<for> loop):

for $iter {...}

Previously Larry has written that last variant as:

for <$iter> {...}

but I think that's...err...differently right. I think the angled version
should invoke C<$iter.next> once (before the C<for> starts iterating) and
then iterate the result of that. In other words, I think that a C<for>
loop argument should always have one implicit level of iteration.

Otherwise I can't see how one call call an iterator directly in a
for loop:

for <fibs()> {...}


But I could certainly live with it not having that, in which case
the preceding example would have to be:

my $iter = fibs();
for <$iter> {...}


and, if your coroutine itself repeatedly yields a iterator
then you need:

my $iter = fibses();
for < <$iter> > {...}

(Careful with those single angles, Eugene!)


>
> class Foo {
> method next { print "Gliddy glub gloopy\n" }
> }
> sub goof () {
> loop {
> print "Nibby nabby nooby\n";
> yield new Foo;

That would have to be:

yield new Foo:;
or:
yield Foo.new;

> }
> }
>
> my $iter = goof;
> print $iter.next; # No.. no! Gliddy! Not Nibby!
>
> How does this work, then?

Calling C<goof> returns an iterator that resumes the body of C<goof>
each time the iterator's C<next> method is called.

Teh actual call to C<$iter.next> resumes the body of C<goof>, which runs
until the next C<yield>, which (in this case) returns an object of class
C<Foo>. So the line:

print $iter.next;

prints "Nibby nabby nooby\n" then the serialization of the Foo object.

If you wanted to print "Nibby nabby nooby\n" and then "Gliddy glub gloopy\n"
you'd write:

print $iter.next.next;
or:
print <$iter.next>;
or:
print < <$iter> >;


> Hang on... is C<while> a topicalizer now?

That's still under consideration. I would like to see the special-case
Perl 5 topicalization of:

while <$iter> {...}

to be preserved in Perl 6. Larry is not so sure. If I can't sway Larry, then
we'd need explicit topicalization there:

while <$iter> -> $_ {...}

which in some ways seems like a backwards step to me.

> So filehandles are just loops that read lines constantly and yield
> them.

Nearly. Filehandles are just iterator objects, each attached to a
coroutine that reads lines constantly and yields them.


> I'm really starting to like the concept of those co-routines :)

Likewise.


> They elegantify stuff.

<tsk> <tsk> If you're going to talk Merkin, talk it propericiously:

"They elegantificatorize stuff"

;-)

Damian

Ken Fox

unread,
Nov 18, 2002, 9:49:24 AM11/18/02
to Damian Conway, perl6-l...@perl.org
Damian Conway wrote:
> my $iter = fibses();
> for < <$iter> > {...}
>
> (Careful with those single angles, Eugene!)

Operator << isn't legal when the grammar is expecting an
expression, right? The < must begin the circumfix <> operator.

Is the grammar being weakened so that yacc can handle it? The
rule engine is still talked about, but sometimes I get the
feeling that people don't want to depend on it.

That < <$iter> > syntax reminds me too much of C++.

- Ken

Austin Hastings

unread,
Nov 18, 2002, 1:16:22 PM11/18/02
to Damian Conway, perl6-l...@perl.org

--- Damian Conway <dam...@conway.org> wrote:
> The semantics of C<for> would simply be that if it is given an
> iterator object (rather than a list or array), then it calls
> that object's iterator once per loop.

By extension, if it is NOT given an iterator object, will it appear to
create one?

That is, can I say

for (@squares)
{
...
if $special.instructions eq 'Advance three spaces'
{
$_.next.next.next;
}
...
}

or some other suchlike thing that will enable me to consistently
perform iterator-like things within a loop, regardless of origin?

(Oh please! Let there be one, and for love of humanity, let it be
called "bork". Pleasepleaseplease!!! It's a shorthand form of "bind or
kontinue", really it is. :-) :-) :-))


> but I think that's...err...differently right.

The verb form is "euph" ? Or "euphemise"?

> Otherwise I can't see how one call call an iterator directly in a
> for loop:
>
> for <fibs()> {...}

Which suggests that fibs is a coroutine, since otherwise its return
value is weird. But

while <fibs()> { ... }

suggests instead behavior rather like while (!eof()), although the
diamond is strange.

So in general, diamonded-function-call implies coroutine/continuation?

> But I could certainly live with it not having that, in which case
> the preceding example would have to be:
>
> my $iter = fibs();
> for <$iter> {...}

That's not horrible, but it does even more damage to expression
folding.

> and, if your coroutine itself repeatedly yields a iterator
> then you need:
>
> my $iter = fibses();
> for < <$iter> > {...}
>
> (Careful with those single angles, Eugene!)

To disagree, vile Aussie! To be looking at perl5's adornmentless
diamond:

perlopentut sez:
POT> When you process the ARGV filehandle using <ARGV>,
POT> Perl actually does an implicit open on each file in @ARGV.
POT> Thus a program called like this:

POT> $ myprogram file1 file2 file3

POT> Can have all its files opened and processed one at a time
POT> using a construct no more complex than:

POT> while (<>) {
POT> # do something with $_
POT> }

This *ought* to work the same in p6.

Since you can modify @ARGV in a pure string context, what's the real
behavior?

If I say: while (<>) {print;} I'm asking for file-scan behavior.

If I say: for (@ARGV) { print; } I'm asking for array-scan behavior.

If I say: for (<@ARGV>) { print; } I'm asking for trouble?

Proposal:

@ARGV is a string array, but <> is topicized in :: (or whatever the
default execution context is called) to iterate over @_MAGIC_ARGV,
which is := @ARGV but of a different class whose iterate behavior
performs an open "<$_" in the background, and iterates serially over
each entry in @ARGV once EOF occurs.

my CoolFileType @MY_ARGV := @ARGV; # Same data, different interface.

for (<@MY_ARGV>) {
print;
}

This is kind of neat, but there needs to be a solid, readable
typecasting mechanism to facilitate the multiple flavors of iteration
-- to convert from one iterator format to another, for example.


> > They elegantify stuff.
>
> <tsk> <tsk> If you're going to talk Merkin, talk it propericiously:
>
> "They elegantificatorize stuff"

We Merkuns don't add, we shorten. That's "elify", to wit:

"Z'at elify the code?"
"Elify - no."

Reduction of length, combined with conservation of ambiguity. Win win
win.

=Austin


__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - Let the expert host your site
http://webhosting.yahoo.com

Damian Conway

unread,
Nov 18, 2002, 3:50:34 PM11/18/02
to perl6-l...@perl.org
Ken Fox wrote:
> Damian Conway wrote:
>
>> my $iter = fibses();
>> for < <$iter> > {...}
>>
>> (Careful with those single angles, Eugene!)
>
>
> Operator << isn't legal when the grammar is expecting an
> expression, right?

Right.


> The < must begin the circumfix <> operator.

Or the circumfix <<...>> operator. Which is the problem here.


> Is the grammar being weakened so that yacc can handle it?

Heaven forbid! ;-)


> The rule engine is still talked about, but sometimes I get the
> feeling that people don't want to depend on it.

That's not the issue.


> That < <$iter> > syntax reminds me too much of C++.

Yes. But since iterating an iterator to get another iterator that
is immediately iterated will (I sincerely hope!) be a very rare
requirement, I doubt it will be anything like the serious inconvenience
it is in C++.

Damian

Damian Conway

unread,
Nov 18, 2002, 4:53:17 PM11/18/02
to perl6-l...@perl.org
Austin Hastings asked:


> By extension, if it is NOT given an iterator object, will it appear to
> create one?

Yep.


> That is, can I say
>
> for (@squares)
> {
> ...
> if $special.instructions eq 'Advance three spaces'
> {
> $_.next.next.next;
> }
> ...
> }
>
> or some other suchlike thing that will enable me to consistently
> perform iterator-like things within a loop, regardless of origin?

If, by C<$_.next.next.next;> you mean "skip the next three elements
of @squares", then no. $_ isn't an alias to the implicit iterator
over @squares; it's an alias for the element of @squares currently
being iterated.

You want (in my formulation):

my $dance = Iterator.new(@squares);
for $dance {


...
if $special.instructions eq 'Advance three spaces' {

$dance.next.next.next;
}
...
}


> (Oh please! Let there be one, and for love of humanity, let it be
> called "bork". Pleasepleaseplease!!! It's a shorthand form of "bind or
> kontinue", really it is. :-) :-) :-))

"Brain on raw krack" more like it ;-)


> So in general, diamonded-function-call implies coroutine/continuation?

That's the problem. I can't see how that works syntactically.


> To disagree, vile Aussie! To be looking at perl5's adornmentless
> diamond:
>

> If I say: while (<>) {print;} I'm asking for file-scan behavior.

Yes. Special case.


> If I say: for (@ARGV) { print; } I'm asking for array-scan behavior.

Yes.


> If I say: for (<@ARGV>) { print; } I'm asking for trouble?

<grin> Under my proposal, you're saying:

* Grab next element of @ARGV
* Iterate that element.

*Unless* the elements of @ARGV in Perl 6 are actually special Iterator-ish,
filehandle-ish objects that happen to also stringify to the command-line
strings. Hmmmmm.


> Proposal:

Seemed very complex to me.


> That's "elify", to wit:
>
> "Z'at elify the code?"
> "Elify - no."

<GROAN>

Damian

Austin Hastings

unread,
Nov 18, 2002, 5:52:17 PM11/18/02
to Damian Conway, perl6-l...@perl.org

--- Damian Conway <dam...@conway.org> wrote:
> Austin Hastings asked:

> > That is, can I say
> >
> > for (@squares)
> > {
> > ...
> > if $special.instructions eq 'Advance three spaces'
> > {
> > $_.next.next.next;
> > }
> > ...
> > }
> >
> > or some other suchlike thing that will enable me to consistently
> > perform iterator-like things within a loop, regardless of origin?
>
> If, by C<$_.next.next.next;> you mean "skip the next three elements
> of @squares", then no. $_ isn't an alias to the implicit iterator
> over @squares; it's an alias for the element of @squares currently
> being iterated.
>
> You want (in my formulation):
>
> my $dance = Iterator.new(@squares);
> for $dance {
> ...
> if $special.instructions eq 'Advance three spaces' {
> $dance.next.next.next;
> }
> ...
> }

How'zat, again? What is the means for extracting the actual VALUE of
$dance? And why is that different for $_-as-iterator?

IOW:

my Iterator $dance = ...;
for <$dance> {
print $_; # should this print the current dance, -> $_ by default?

print $dance;

# Should the above be ".value()"
# or ".next()"
# or ".toString()" ?

print <$dance>; # Obviously "get next value and advance" a la p5

}

Also, in your formulation:

> my $dance = Iterator.new(@squares);
> for $dance {

What happens when iterators require magic state info? It seems more
appropriate to define a CLASS.iterator method, which overloads a
simplistic default. ("fail" in scalar cases, iterative for Array and
Hash)

> > (Oh please! Let there be one, and for love of humanity, let it be
> > called "bork". Pleasepleaseplease!!! It's a shorthand form of "bind
> or
> > kontinue", really it is. :-) :-) :-))
>
> "Brain on raw krack" more like it ;-)

Whatever! As long as I get to say:

for my <@Swedish> -> $chef {
$chef.bork.bork.bork;
}

Perlmuppets, anyone?

> > So in general, diamonded-function-call implies
> coroutine/continuation?
>
> That's the problem. I can't see how that works syntactically.

I was thinking in terms of "reading", not "parsing" -- that is, "when a
coder reads diamonded-function-call, the reflex will be 'this is a
continuation'" -- valuable clues.


> > To disagree, vile Aussie! To be looking at perl5's adornmentless
> > diamond:
> >
> > If I say: while (<>) {print;} I'm asking for file-scan behavior.
>
> Yes. Special case.

But a special case of WHAT?

> > If I say: for (<@ARGV>) { print; } I'm asking for trouble?
>
> <grin> Under my proposal, you're saying:
>
> * Grab next element of @ARGV
> * Iterate that element.

That's the problem. Why would the second point "* Iterate that element"
happen? We've already GOT a flattener. If I want recursive iteration I
can say:

for (<*@ARGV>) { print; }

or maybe

for (*<@ARGV>) { print; }

I can't be sure.

> *Unless* the elements of @ARGV in Perl 6 are actually special
> Iterator-ish,
> filehandle-ish objects that happen to also stringify to the
> command-line
> strings. Hmmmmm.

I thought of that one first, but discarded it.


> > Proposal:
>
> Seemed very complex to me.

It's because I discarded the "@ARGV is magic that stringifies" option.
In other words, let @ARGV be normal, first and foremost. Then apply
magic to it.

That way, I can argue for being able to apply the SAME magic to
something else, rather than trying to fight with having to reimplement
the @ARGV magic class.

my @file_names = ( list of strings );
my FileIterator @argv_alike := @file_names;

while (<@argv_alike>) {
...
}

Now the question is, how do I get it into $_/@_/whatever_, so that I
can use <> instead of <@argv_alike>? (I avoid simply slapping it into
@_ because I vaguely recall something about the inevitable demise of
@_-as-arglist etc. But that was before the weekend, when there were
more brain cells.)


> <GROAN>

Warning: File iterator used in void context. Possible loss of data.

Larry Wall

unread,
Nov 18, 2002, 9:02:49 PM11/18/02
to Damian Conway, perl6-l...@perl.org
On Tue, Nov 19, 2002 at 08:53:17AM +1100, Damian Conway wrote:
: my $dance = Iterator.new(@squares);
: for $dance {

Scalar variables have to stay scalar in list context, so $dance cannot
suddenly start behaving like a list. Something must tell the scalar
to behave like a list, and I don't think I want C<for> to do that.
A C<for> should just take an ordinary list.

So you can do it any of these ways:

for <$dance> {

for $dance.each {

for each $dance: {
^ note colon

Then there's this approach to auto-iteration:

my @dance := Iterator.new(@squares);
for @dance {

Larry

Damian Conway

unread,
Nov 18, 2002, 9:51:56 PM11/18/02
to Larry Wall, perl6-l...@perl.org
Larry wrote:

> So you can do it any of these ways:
>
> for <$dance> {
>
> for $dance.each {
>
> for each $dance: {
> ^ note colon
>
> Then there's this approach to auto-iteration:
>
> my @dance := Iterator.new(@squares);
> for @dance {

Okay, so now I need to make sense of the semantics of <...> and
C<for> and coroutines and their combined use.

Is the following correct?

==============================================================================

The presence of a C<yield> automatically makes a subroutine a coroutine:

sub fibs {
my ($a, $b) = (0, 1);
loop {
yield $b;
($a, $b) = ($b, $a+$b);
}
}

Calling such a coroutine returns an Iterator object with (at least)
the following methods:

next() # resumes coroutine body until next C<yield>

next(PARAM_LIST) # resumes coroutine body until next C<yield>,
# rebinding params to the args passed to C<next>.
# PARAM_LIST is the same as the parameter list
# of the coroutine that created the Iterator

each() # returns a lazy array, each element of which
# is computed on demand by the appropriate
# number of resumptions of the coroutine body


In a scalar context:

<$fh> # Calls $fh.readline (or maybe that's $fh.next???>
<$iter> # Calls $iter.next
fibs() # Returns iterator object
<fibs()> # Returns iterator object and calls that
# object's C<next> method (see note below)

In a list context:

<$fh> # Calls $fh.each
<$iter> # Calls $iter.each
fibs() # Returns iterator object
<fibs()> # Returns iterator object and calls object's C<each>


So then:

for <$fh> {...} # Build and then iterate a lazy array (the elements
# of which call back to the filehandle's input
# retrieval coroutine)

for <$iter> {...} # Build and then iterate a lazy array (the elements
# of which call back to the iterator's coroutine)

for fibs() {...} # Loop once, setting $_ to the iterator object
# that was returned by C<fibs>

for <fibs()> {...} # Build and then iterate a lazy array (the elements
# of which call back to the coroutine of the
# iterator returned by C<fibs>


==============================================================================

Note: this all hangs together *very* nicely, except when someone writes:

loop {
my $nextfib = <fibs()>;
...
}

In which case $nextfib is perennially 1, since every call to C<fibs>
returns a new Iterator object.

The solution is very simple, of course:

my $nextfib = <my $iter//=fibs()>;

but we might want to contemplate issuing a warning when someone calls
an argumentless coroutine within a scalar context <...>.

Damian

Ken Fox

unread,
Nov 18, 2002, 10:21:01 PM11/18/02
to perl6-l...@perl.org
Damian Conway wrote:

> Ken Fox wrote:
>> The < must begin the circumfix <> operator.
>
> Or the circumfix <<...>> operator. Which is the problem here.

This is like playing poker with God. Assuming you can get over
the little hurdles of Free Will and Omniscience, there's still
the problem of Him pulling cards out of thin air.

What does the circumfix <<...>> operator do? [1]

Here docs are re-syntaxed and the << introducer was stolen
for the <<...>> operator? [2]

> Yes. But since iterating an iterator to get another iterator that
> is immediately iterated will (I sincerely hope!) be a very rare
> requirement, I doubt it will be anything like the serious inconvenience
> it is in C++.

True. I suppose even multi-dimensional data structures will
rarely be iterated over with a simple:

for < <$array> > {
}

Most people will probably want more control:

for <$array> {
for <$_> {
}
}

Anyways, I was wondering about the general principle of using
C++ style hacks to make yacc happy. I should have known better
coming from the author of "C++ Resyntaxed". Did the immodest
proposal fix < <> > syntax? ;)

- Ken

[1] I can't google for <<. Anybody know if Google can add perl6
operators to their word lists? Seriously!

[2] Hmm. Will the uproar on here docs beat string concatenation?

Damian Conway

unread,
Nov 18, 2002, 10:29:46 PM11/18/02
to perl6-l...@perl.org
Ken Fox lamented:

>> Or the circumfix <<...>> operator. Which is the problem here.
>
> This is like playing poker with God.

I hear God prefers dice.


> What does the circumfix <<...>> operator do?

It's the ASCII synonym for the «...» operator, which is a
synonym for the qw/.../ operator.


> Here docs are re-syntaxed and the << introducer was stolen
> for the <<...>> operator?

Nope. Heredocs still start with <<.


> Anyways, I was wondering about the general principle of using
> C++ style hacks to make yacc happy. I should have known better
> coming from the author of "C++ Resyntaxed". Did the immodest
> proposal fix < <> > syntax? ;)

But of course! In SPECS, type parameters live in unambiguously
nestable (and yacc parsable) <[...]> delimiters.

Damian

Ken Fox

unread,
Nov 18, 2002, 10:42:59 PM11/18/02
to perl6-l...@perl.org
Damian Conway wrote:
> It's [<<...>>>] the ASCII synonym for the «...» operator, which

> is a synonym for the qw/.../ operator.

> Nope. Heredocs still start with <<.

Hey! Where'd *that* card come from? ;)

Seriously, that's a good trick. How does it work? What do these
examples do?

print <<"a" "b" "c">>;

print <<"a"
"b"
"c">>;
a

Is it illegal now to use quotes in qw()?

- Ken

David Wheeler

unread,
Nov 18, 2002, 10:54:00 PM11/18/02
to Damian Conway, Larry Wall, perl6-l...@perl.org
On Monday, November 18, 2002, at 06:51 PM, Damian Conway wrote:

> for <$fh> {...} # Build and then iterate a lazy array (the elements
> # of which call back to the filehandle's input
> # retrieval coroutine)
>
> for <$iter> {...} # Build and then iterate a lazy array (the elements
> # of which call back to the iterator's coroutine)
>
> for fibs() {...} # Loop once, setting $_ to the iterator object
> # that was returned by C<fibs>
>
> for <fibs()> {...} # Build and then iterate a lazy array (the elements
> # of which call back to the coroutine of the
> # iterator returned by C<fibs>

How will while behave?

while <$fh> {...} # Iterate until $fh.readline returns EOF?

while <$iter> {...} # Iterate until $iter.each returns false?

while fibs() {...} # Infinite loop -- fibs() returns an
# iterator every time?

while <fibs()> {...} # I'm afraid to ask!

Best,

David

--
David Wheeler AIM: dwTheory
da...@wheeler.net ICQ: 15726394
http://david.wheeler.net/ Yahoo!: dew7e
Jabber: The...@jabber.org

Damian Conway

unread,
Nov 18, 2002, 10:50:02 PM11/18/02
to perl6-l...@perl.org
> Seriously, that's a good trick. How does it work? What do these
> examples do?
>
> print <<"a" "b" "c">>;

Squawks about finding the string "b" immediately after the heredoc introducer.


> print <<"a"
> "b"
> "c">>;

Likewise.


> Is it illegal now to use quotes in qw()?

Nope. Only as the very first character of a <<...>>.

So any of these are still fine:

print << "a" "b" "c" >>;
print <<\"a" "b" "c">>;
print «\"a" "b" "c"»;

print qw/"a" "b" "c"/;

Damian

Luke Palmer

unread,
Nov 18, 2002, 11:05:35 PM11/18/02
to dam...@conway.org, la...@wall.org, perl6-l...@perl.org
> Mailing-List: contact perl6-lan...@perl.org; run by ezmlm
> X-Sent: 19 Nov 2002 02:51:54 GMT
> Date: Tue, 19 Nov 2002 13:51:56 +1100
> From: Damian Conway <dam...@conway.org>
> X-Accept-Language: en, en-us
> Cc: "perl6-l...@perl.org" <perl6-l...@perl.org>
> X-SMTPD: qpsmtpd/0.12, http://develooper.com/code/qpsmtpd/

>
> Larry wrote:
>
> > So you can do it any of these ways:
> >
> > for <$dance> {
> >
> > for $dance.each {
> >
> > for each $dance: {
> > ^ note colon
> >
> > Then there's this approach to auto-iteration:
> >
> > my @dance := Iterator.new(@squares);
> > for @dance {
>
> Okay, so now I need to make sense of the semantics of <...> and
> C<for> and coroutines and their combined use.
>
> Is the following correct?
>
> ==============================================================================
[snip]
> ==============================================================================


I like this I<much> better than what you explained before. Most of my
problems with two iterators to the same thing in the same scope are
gone, as well as the confusions I had about C<for>.

Luke

Damian Conway

unread,
Nov 18, 2002, 11:05:54 PM11/18/02
to perl6-l...@perl.org
David Wheeler asked:

> How will while behave?

C<while> evaluates its first argument in scalar context, so:


> while <$fh> {...} # Iterate until $fh.readline returns EOF?

More or less. Technically: call <$fh.next> and execute the loop body if that method
returns true. Whether it still has the automatic binding to $_ and the implicit
definedness check is yet to be decided.


> while <$iter> {...} # Iterate until $iter.each returns false?

Yes.


> while fibs() {...} # Infinite loop -- fibs() returns an
> # iterator every time?

I suspect so.


> while <fibs()> {...} # I'm afraid to ask!

Usually an infinite loop. C<fibs()> returns a new iterator every time,
which <...> then calls C<next> on.

Damian

Damian Conway

unread,
Nov 18, 2002, 11:17:45 PM11/18/02
to perl6-l...@perl.org
David Wheeler asked:

>>> while <$fh> {...} # Iterate until $fh.readline returns EOF?

> That's a scalar context?

Sure. C<while> always evaluates its condition in a scalar context.

Damian

Luke Palmer

unread,
Nov 18, 2002, 11:11:50 PM11/18/02
to dam...@conway.org, perl6-l...@perl.org
> Date: Tue, 19 Nov 2002 14:29:46 +1100
> From: Damian Conway <dam...@conway.org>
>
> Ken Fox lamented:
>
> >> Or the circumfix <<...>> operator. Which is the problem here.
> >
> > This is like playing poker with God.
>
> I hear God prefers dice.
>
>
> > What does the circumfix <<...>> operator do?
>
> It's the ASCII synonym for the «...» operator, which is a
> synonym for the qw/.../ operator.

I did not have Unicode working during the dreaded operator thread.
What was the final syntax for vector ops?

@a ≪+≫ @b
@a ≫+≪ @b
Something else?

If the former, how does one disambiguate a qw with a unary vector op?

Luke

David Wheeler

unread,
Nov 18, 2002, 11:32:38 PM11/18/02
to Damian Conway, perl6-l...@perl.org
On Monday, November 18, 2002, at 08:17 PM, Damian Conway wrote:

> Sure. C<while> always evaluates its condition in a scalar context.

Oh, duh. Thanks.

Damian Conway

unread,
Nov 18, 2002, 11:19:17 PM11/18/02
to perl6-l...@perl.org
Luke Palmer asked:

> What was the final syntax for vector ops?
>
> @a ≪+≫ @b
> @a ≫+≪ @b

The latter (this week, at least ;-).

Damian

Iain 'Spoon' Truskett

unread,
Nov 18, 2002, 11:24:03 PM11/18/02
to perl6-l...@perl.org
* Damian Conway (dam...@conway.org) [19 Nov 2002 15:19]:

> Luke Palmer asked:
> > What was the final syntax for vector ops?
> >
> > @a ???+??? @b
> > @a ???+??? @b

> The latter (this week, at least ;-).

Y'know, for those of us who still haven't set up Unicode, they look
remarkably similar =)


cheers,
--
Iain.

David Wheeler

unread,
Nov 18, 2002, 11:11:37 PM11/18/02
to Damian Conway, perl6-l...@perl.org
On Monday, November 18, 2002, at 08:05 PM, Damian Conway wrote:

>> while <$fh> {...} # Iterate until $fh.readline returns EOF?
>
> More or less. Technically: call <$fh.next> and execute the loop body
> if that method
> returns true. Whether it still has the automatic binding to $_ and the
> implicit
> definedness check is yet to be decided.

That's a scalar context? I assumed it was list context from your
previous post:

> In a list context:
>
> <$fh> # Calls $fh.each

At any rate, I hope that it's bound to $_ -- nice conversion from Perl
5's behavior, that.

Damian Conway

unread,
Nov 18, 2002, 11:47:27 PM11/18/02
to perl6-l...@perl.org
Iain 'Spoon' Truskett wrote:

>>> @a ???+??? @b
>>> @a ???+??? @b
>

> Y'know, for those of us who still haven't set up Unicode, they look
> remarkably similar =)

"Think Of It As Evolution In Action"

;-)

Damian

David Wheeler

unread,
Nov 18, 2002, 11:49:27 PM11/18/02
to Damian Conway, perl6-l...@perl.org
On Monday, November 18, 2002, at 08:19 PM, Damian Conway wrote:

>> What was the final syntax for vector ops?
>> @a ≪+≫ @b
>> @a ≫+≪ @b
>
> The latter (this week, at least ;-).

This reminds me: I though of another set of bracing characters that I
don't recall anyone ever mentioning before, and that might be useful in
some context where such a thing is needed.

C< \op/ > or C< /op\ >

I realize that there could be issues with patterns, but the first
example ought to avoid that, I would think. If someone *has* thought of
these characters as complementary braces (why wouldn't someone have?),
well, just forget about it.

Paul Johnson

unread,
Nov 19, 2002, 7:43:56 AM11/19/02
to dam...@conway.org, perl6-l...@perl.org

Damian Conway said:

>> Is it illegal now to use quotes in qw()?
>
> Nope. Only as the very first character of a <<...>>.

Paging Mr Cozens. ;-)

> So any of these are still fine:
>
> print << "a" "b" "c" >>;
> print <<\"a" "b" "c">>;
> print «\"a" "b" "c"»;

Presumably without the backslash here too.

> print qw/"a" "b" "c"/;

--
Paul Johnson - pa...@pjcj.net
http://www.pjcj.net

Austin Hastings

unread,
Nov 19, 2002, 10:44:56 AM11/19/02
to Damian Conway, perl6-l...@perl.org

--- Damian Conway <dam...@conway.org> wrote:

This coming from someone whose national bird is the platypus?

fear...@figaro.weizmann.ac.il

unread,
Nov 19, 2002, 2:21:04 PM11/19/02
to Damian Conway, perl6-l...@perl.org
Damian Conway writes:
> David Wheeler asked:
>
> > How will while behave?
>
> C<while> evaluates its first argument in scalar context, so:
>
>
> > while <$fh> {...} # Iterate until $fh.readline returns EOF?
>
> More or less. Technically: call <$fh.next> and execute the loop
> body if that method returns true. Whether it still has the
> automatic binding to $_ and the implicit definedness check is yet
> to be decided.
>
>
> > while <$iter> {...} # Iterate until $iter.each returns false?
>
> Yes.
>

you mean "Iterate until $iter.next returns false?"


what is the difference between the Iterator and lazy array ?

am I right that it is just "interface" : lazy array is an iterator
object "inside" Array interface : ????

Larry Wall wrote:
> Then there's this approach to auto-iteration:
>
> my @dance := Iterator.new(@squares);
> for @dance {

but then each is very simple method :

class Iterator {
method each( $self:) {
my @a := $self ;
return @a ;
}
}

but then probably we dont need two methods -- next and each .
just like in perl5 each can determine the calling context

class Iterator {
method each( $self:) {
when want Scalar {
...
}
when want Array {
my @a := $self ;
return @a ;
}
}
}

and then <...> could be *really* the sugar for .each ( or .next if it
will be called so ) . in these examples


> In a scalar context:
>
> <$fh> # Calls $fh.readline (or maybe that's $fh.next???>
> <$iter> # Calls $iter.next
> fibs() # Returns iterator object
> <fibs()> # Returns iterator object and calls that
> # object's C<next> method (see note below)
>
>

> In a list context:
>
> <$fh> # Calls $fh.each

> <$iter> # Calls $iter.each
> fibs() # Returns iterator object
> <fibs()> # Returns iterator object and calls object's C<each>
>

<...> *always* force call to .each ( which is context aware ) .

but again all that is based on the assumtion that lazy array is just
Iterator object in the "cloth" of array ( variable container ) . so
this is a question .

arcadi


Austin Hastings

unread,
Nov 19, 2002, 1:21:10 PM11/19/02
to Damian Conway, Larry Wall, perl6-l...@perl.org
> Larry wrote:
>
> So you can do it any of these ways:
>
> for <$dance> {
>
> for $dance.each {
>
> for each $dance: {
> ^ note colon

1- Why is the colon there? Is this some sub-tile syntactical new-ance
that I missed in a prior message, or a new thing?

2- Why is the colon necessary? Isn't the "each $dance" just a
bassackwards method invocation (as C<close $fh> is to C<$fh.close()>)?

> Then there's this approach to auto-iteration:
>
> my @dance := Iterator.new(@squares);
> for @dance {

I think this is called "avoiding the question". Now you've converted an
Iterator into an iterator masked behind an array, and asked the C<for>
keyword to create apparently a "private" iterator to traverse it. That
seems like twice as much work for the same output.

Also, I have a problem with the notion of the Iterator class being
tasked with creation of iterators -- how do you deal with objects (even
TIEd arrays) that require magic iterators? Better to ask the class to
give you one. (Of course, C<Iterator.new()> could internally ask
@squares to provide an iterator, but again that adds a layer for little
apparent gain.

> Damian Conway wrote:
> The presence of a C<yield> automatically makes a subroutine a
> coroutine:
>
> sub fibs {
> my ($a, $b) = (0, 1);
> loop {
> yield $b;
> ($a, $b) = ($b, $a+$b);
> }
> }
>
> Calling such a coroutine returns an Iterator object with (at least)
> the following methods:
>
> next() # resumes coroutine body until next C<yield>
>
> next(PARAM_LIST) # resumes coroutine body until next C<yield>,
> # rebinding params to the args passed to C<next>.
> # PARAM_LIST is the same as the parameter list
> # of the coroutine that created the Iterator

What's the value of C<next(PARAM_LIST)>? Is this just a shortcut for
re-initializing the iterator? How is this going to work when the
iterator has opened files or TCP connections based on the parameter
list?

my $iter = DNS.iterator(".com.");

while <$iter> {
$iter.next(".com.au.")
if not hackable($_);
}

Furthermore, what's the syntax for including arguments to next in a
diamond operator?

while <$iter>($a, $b) {
...
$a += 2;
}

> each() # returns a lazy array, each element of which
> # is computed on demand by the appropriate
> # number of resumptions of the coroutine body

What's the difference between a lazy array and an iterator? Is there
caching? What about the interrelationships between straight iteration
and iteration interrupted by a reset of the parameter list? Or does
calling $iter.next(PARAM_LIST) create a new iterator or wipe the cache?
How do multiple invocations of each() interact with each other? (E.g.,
consider parsing a file with block comment delimiters: one loop to read
lines, and an inner loop to gobble comments (or append to a delimited
string -- same idea). These two have to update the same file pointer,
or all is lost.)

Some of questions about iterators and stuff:

1- Are iterators now considered a fundamental type?

1a- If so, are they iterators or Iterators? (See 2b1, below)

1b- What value would iterators (small-i) have? Is it a meaningful idea?

2- What is the relationship between iterators and arrays/lists?

2a- Is there an C<Iterator.toArray()> or C<.toList()> method?

2a1- The notion that Iterator.each() returns a lazy array seems a
little wierd. Isn't a lazy array just an iterator? Why else have the
proposed syntax for Iterator.next(PARAM_LIST)? (Admittedly the
PARAM_LIST doesn't have to be a single integer, like an array.) Or is
that what a small-i iterator is?

2b- Is there a C<List.iterator()> method? Or some other standard way of
iterating lists?

2b1- Are these "primitive" interfaces to iteration, in fact
overridable? That is, can I override some "operator"-like method and
change the behavior of

while <$fh> { print; }

2b2- Is that what C<each> does in scalar context -- returns an
iterator?

my $iter = each qw(apple banana cherry);

my $junk = all qw(apple banana cherry);
my $itr2 = each $junk; # Whoops! Wrong thread...

3- What's the difference among an iterator, a coroutine, and a
continuation?

3a- Does imposing Damian's iterator-based semantics for coroutines
(and, in fact, imposing his definition of "any sub-with-yield ==
coroutine") cause loss of desirable capability? (Asked in ignorance --
the only coroutines I've ever dealt with were written in assembly
language, so I don't really know anything about what they can be used
to do.)

3b- Is there a corresponding linkage between continuations and some
object, a la coroutine->iterator?

3c- Is there a tie between use of continuations and use of thread or
IPC functionality? Is it a prohibitive tie, one way or the other? That
is, I've been thinking that "A coroutine is just a continuation." But
if "A continuation implies <...>", for example a semaphore or a thread,
or some such, then that may be too expensive. (More ignorance on my
part, I'm sure.)

3d- Conversely, what happens when continuations, coroutines, or
iterators are used in a threaded environment? Will there need to be
locking?

4- Given the historical behavior of binding $_ to the actual data in
question (thus making it modifiable via $_) what's the correct behavior
for iterators? Will they "upvar", or return a ref, or what? How do I
write that?

sub fibs()


{
my ($a, $b) = (0, 1);
loop {
yield $b;

($a, $b) = ($b, $b + $a);
}
}

for <fibs()> {
when 13 { $_ = 100; }

print "$_\n";
}

DWIM? ( ... 5, 8, 13, 100, 113, ... )


> In a scalar context:
>
> <$fh> # Calls $fh.readline (or maybe that's $fh.next???>

I think it's $fh.next. $fh.next calls $fh.readline, or not, or is :=
$fh.readline, or whatever. Keep it simple.

my $i = 0;
while <$i> {

Should integer.next() be operator:++ ? :-)

> <$iter> # Calls $iter.next
> fibs() # Returns iterator object
> <fibs()> # Returns iterator object and calls that
> # object's C<next> method (see note below)


> In a list context:
>
> <$fh> # Calls $fh.each
> <$iter> # Calls $iter.each
> fibs() # Returns iterator object
> <fibs()> # Returns iterator object and calls object's C<each>
>
>
> So then:
>
> for <$fh> {...} # Build and then iterate a lazy array (the

> # elements of which call back to the
> # filehandle's input retrieval coroutine)

(FWIW: I think they call .next(), and .next() can call the input
retrieval coroutine or not.)

Okay, I think I'm seeing why the lazy array bit is needed.

So is it true that an iterator must be arrayificable? Or listificable?

Also, what happens when <$fh> or <$iter> is called in scalar context
within a loop? Surely that must update the "secret" iterator that is
being run by the loop control?

That is:

for <$fh> {
...
if /$start_of_block/ {
my $block = "";
while <$fh> {
leave loop if /$end_of_block/;
$block ~= $_; # Or WFE the string concat operator winds up.
}
}
}

The two loops must update the same iterator, so any "lazy array" bits
have to update as well. Ah well, that's for Dan &co.


=Austin

Damian Conway

unread,
Nov 20, 2002, 3:35:44 PM11/20/02
to perl6-l...@perl.org
Paul Johnson wrote:

>>>Is it illegal now to use quotes in qw()?
>>
>>Nope. Only as the very first character of a <<...>>.
>
> Paging Mr Cozens. ;-)

It's just another instance of whitespace significance.

>> print «\"a" "b" "c"»;
>
> Presumably without the backslash here too.

Maybe. It depends on whether Larry decides to make « and <<
synonyms in all contexts (in which case: no).

Damian

Damian Conway

unread,
Nov 20, 2002, 3:44:35 PM11/20/02
to perl6-l...@perl.org
Arcadi wrote:

> > > > > while <$iter> {...} # Iterate until $iter.each returns false?
>

> > you mean "Iterate until $iter.next returns false?"

Oops. Quite so.


> what is the difference between the Iterator and lazy array ?
>
> am I right that it is just "interface" : lazy array is an iterator
> object "inside" Array interface : ????

That's one particular implementation of a lazy array, yes.

Another implementation is an array interface with an subroutine that
maps indices onto values. Perl 6 will undoubtedly need both,
and maybe others as well.

Damian


Damian Conway

unread,
Nov 20, 2002, 8:39:43 PM11/20/02
to perl6-l...@perl.org
Austin Hastings wrote:

>> for each $dance: {
>> ^ note colon
>
>
> 1- Why is the colon there? Is this some sub-tile syntactical new-ance
> that I missed in a prior message, or a new thing?

It's the way we mark an indirect object in Perl 6.


> 2- Why is the colon necessary? Isn't the "each $dance" just a
> bassackwards method invocation (as C<close $fh> is to C<$fh.close()>)?

Yes. The colon is needed because the colon-less Perl 5 indirect object
syntax is inherently ambiguous. Adding the colon in Perl 6 fixes the
many nasty, subtle problems that Perl 5's syntax had.


> I think this is called "avoiding the question". Now you've converted an
> Iterator into an iterator masked behind an array, and asked the C<for>
> keyword to create apparently a "private" iterator to traverse it.

There's no second iterator. Just C<for> walking through an array.


> What's the value of C<next(PARAM_LIST)>? Is this just a shortcut for
> re-initializing the iterator?

No. It uses the original coroutine but rebinds its parameters to the new
arguments passed to C<next>.


> How is this going to work when the
> iterator has opened files or TCP connections based on the parameter
> list?

The original files or connections will be unaffected.


> Furthermore, what's the syntax for including arguments to next in a
> diamond operator?

I very much doubt there would be one. If you need to pass arguments,
you'd call C<next> explicitly.


> What's the difference between a lazy array and an iterator? Is there
> caching?

Yes. A lazy array is a wrapper-plus-cache around an iterator.


> What about the interrelationships between straight iteration
> and iteration interrupted by a reset of the parameter list?

Resetting the parameter list doesn't interrupt iteration.


> Or does
> calling $iter.next(PARAM_LIST) create a new iterator or wipe the cache?

No.


> How do multiple invocations of each() interact with each other? (E.g.,
> consider parsing a file with block comment delimiters: one loop to read
> lines, and an inner loop to gobble comments (or append to a delimited
> string -- same idea). These two have to update the same file pointer,
> or all is lost.)

So pass the file pointer to the original continuation.


> Some of questions about iterators and stuff:
>
> 1- Are iterators now considered a fundamental type?

Probably, since they're fundamental to I/O and C<for> loops.


> 1a- If so, are they iterators or Iterators? (See 2b1, below)

class Iterator {...}


> 1b- What value would iterators (small-i) have? Is it a meaningful idea?

Depends what you mean by it. ;-)


> 2- What is the relationship between iterators and arrays/lists?

None. Except that some arrays/lists may be implemented using Iterators.


> 2a- Is there an C<Iterator.toArray()> or C<.toList()> method?

Iterator::each.


> 2a1- The notion that Iterator.each() returns a lazy array seems a
> little wierd. Isn't a lazy array just an iterator?

No. It's an array that populates itself on-demand using an iterator.


> 2b- Is there a C<List.iterator()> method? Or some other standard way of
> iterating lists?

Probably.


> 2b1- Are these "primitive" interfaces to iteration, in fact
> overridable? That is, can I override some "operator"-like method and
> change the behavior of
>
> while <$fh> { print; }

Sure. Derive a class from Iterator and change its C<next> method.


> 2b2- Is that what C<each> does in scalar context -- returns an
> iterator?

No. C<each> returns a lazy array, so in a scalar context it returns
a reference to the lazy array.


> 3- What's the difference among an iterator, a coroutine, and a
> continuation?

Iterator: an object that returns successive values from some source
(such as an array, a filehandle, or a coroutine)

Coroutine: a subroutine whose state is preserved when it returns
such that it may be restarted from the point of previous
return, rather than from the start of the subroutine

Continuation: a mechanism for capturing the "what-happens-next"
at any point in a program's execution

BTW, there's rather a nice discussion of these three at:
http://mail.python.org/pipermail/python-dev/1999-July/000467.html


> 3a- Does imposing Damian's iterator-based semantics for coroutines
> (and, in fact, imposing his definition of "any sub-with-yield ==
> coroutine") cause loss of desirable capability?

No. Not compared to other potential coroutine semantics.


> 3b- Is there a corresponding linkage between continuations and some
> object, a la coroutine->iterator?

Continuations can be used to implement virtually any control structure.
In a sense they link to everything.


> 3c- Is there a tie between use of continuations and use of thread or
> IPC functionality?

Hmmm. I *suppose* a continuation could continue into a different thread.
That might be something worth proscribing. ;-)

> 3d- Conversely, what happens when continuations, coroutines, or
> iterators are used in a threaded environment? Will there need to be
> locking?

Yes. Threaded environments *always* require locking at some level.


> 4- Given the historical behavior of binding $_ to the actual data in
> question (thus making it modifiable via $_) what's the correct behavior
> for iterators? Will they "upvar", or return a ref, or what? How do I
> write that?

C<yield> is just a C<return> that can...err...come back. So, if you
want to return an lvalue, you declare the coroutine to do so:

sub fibs() is rw {


my ($a, $b) = (0, 1);
loop {
yield $b;
($a, $b) = ($b, $b + $a);
}
}

for <fibs()> {
when 13 { $_ = 100; }

print "$_\n";
}

Of course, given the implementation of C<fibs>
that will print: 1, 1, 2, 3, 5, 8, 100, 108, 208, 316, etc.

> my $i = 0;
> while <$i> {
>
> Should integer.next() be operator:++ ? :-)

No! ;-)

> So is it true that an iterator must be arrayificable? Or listificable?

If a class inherits from Iterator, it will automatically have the
appropriate C<each> method that wraps its associated coroutine in an array.
If you chose to override that functionality, well, _caveat derivor_!


> Also, what happens when <$fh> or <$iter> is called in scalar context
> within a loop? Surely that must update the "secret" iterator that is
> being run by the loop control?
>
> That is:
>
> for <$fh> {
> ...
> if /$start_of_block/ {
> my $block = "";
> while <$fh> {
> leave loop if /$end_of_block/;
> $block ~= $_; # Or WFE the string concat operator winds up.
> }
> }
> }
>
> The two loops must update the same iterator, so any "lazy array" bits
> have to update as well.

It means that the lazy array will not contain the lines that were read
by the inner iteration. So the code will behave as expected (i.e. process
each line from the file exactly once).

Damian

fear...@figaro.weizmann.ac.il

unread,
Nov 21, 2002, 12:03:36 PM11/21/02
to Damian Conway, perl6-l...@perl.org
Damian Conway writes:
>
> There's no second iterator. Just C<for> walking through an array.
>

( questions in the form of answers :-)

so :
* "for" impose array context for first argument and doesnt care about
"nature" of the array which it was given eventually as an argument .
no multiple streams -- use parallel and friends.

* parallel and friends return lazy array ( for performance
considerations ???? ) _o_r_ "for" *notice* the parallel and ??? optimize
it away / dont know

for parallel(@a,@b) -> ($x,$y) { ... }

* every object with "next" method can function as iterator ???
_o_r_ we always have to inherit from "iterator" class .
what about reset/rewind ???

* $fh = open "myfile" ;
for <$fh> { ... while <$fh> { ... } ... }

both <$fh> *ultimately* use *the same* method call $fh.next , but
second <$fh> does it explicitely , while the first -- from under the
cloth of lazy array returned by $fh.each and "drived" by "for" .

* what does it mean that "for walks the array" ( keeping in mind that
that array may be usual or lazy and for have to not to care )

> >
> > What's the difference between a lazy array and an iterator? Is there
> > caching?
>
> Yes. A lazy array is a wrapper-plus-cache around an iterator.
>

$fh = open "file" ;
@a := $fh ;
print @a[3] # 4 calls to "$fh.next"
print @a[0] # no calls to "$fh.next"

is that the meaning of ...-plus-cache ????


>
> > Some of questions about iterators and stuff:
> >
> > 1- Are iterators now considered a fundamental type?
>
> Probably, since they're fundamental to I/O and C<for> loops.
>
>

so every class can define its own "next" method or inherit from
Iterator to be used as an iterator _o_r_ it ( class ) *always* have to
inherit from Iterator -- to be used as iterator ???
Naively , it seems that this is similar to booleans in perl -- no need to
inherit from special class to behave as boolean.

>
> > 2a- Is there an C<Iterator.toArray()> or C<.toList()> method?
>
> Iterator::each.
>
>
> > 2a1- The notion that Iterator.each() returns a lazy array seems a
> > little wierd. Isn't a lazy array just an iterator?
>
> No. It's an array that populates itself on-demand using an iterator.
>

what is the difference between the arrays @a, @b , ... here
????

$a = Iterator.new( ... )
@a = $a.each ;
@b := $a.each ;
@c := $a ;
@d is lazy = ( 1, 2, 3 ) ;
@f is lazy = $a.each ;


> Iterator: an object that returns successive values from some source
> (such as an array, a filehandle, or a coroutine)

isnt it *anything* having method "next" ???
why do I need a special type "iterator" ?


thanks ,

arcadi .

0 new messages