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
> 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
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
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
> 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
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
> 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
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
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.
> 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
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
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
>>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
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
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
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
> 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
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.
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
> 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
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?
>> 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
> 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
> 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
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
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
> 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
>>> 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
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
> Sure. C<while> always evaluates its condition in a scalar context.
Oh, duh. Thanks.