> --- Michael Lazzaro <[EMAIL PROTECTED]> wrote:
> > 
> > On Wednesday, May 28, 2003, at 01:01 PM, Austin Hastings wrote:
> > > Exampling:
> > >
> > > sub traverse(Hash $tree) {
> > >   return unless $tree;
> > >
> > >   traverse $tree{left} if $tree{left};
> > >   yield $tree{node};
> > >   traverse $tree{right} if $tree{right};
> > > }
> > >
> > > my %hash is Tree;
> > > my &cotrav := coro &traverse(%hash);
> > > print $_ for <ctrav.resume>;
> > >
> > > my &thtrav := thread &traverse(%hash);
> > > print $_ for <thtrav.resume>;
> > 
> > 
> > Hmm.  I think that having _anything_ on the caller side that has to 
> > change based on whether the called thing is a subroutine vs. a 
> > coroutine probably defeats one of the most central purposes of 
> > coroutines -- that nifty subroutine-like abstraction that makes it 
> > "just work".  Consider, under Damian's latest model:
> > 
> >      for <foo()> {...}
> > 
> > It doesn't matter whether foo() is a closure or function returning a 
> > list, lazy list, or iterator, or is a coroutine returning it's .next 
> > value.  Which is excellent, and, I'd argue, the whole point; I'm not 
> > sure that we can have any coroutine syntax that _doesn't_ do that,
> > can we?
> 
> Given that I can say:
> 
>   sub do_foo {...}
>   my &foo := coro &do_foo;
> 
> I can still provide the "transparent" behavior you're wanting.
> 
> > But, as Luke pointed out, some of the other syntax required to make 
> > that work is isn't particularly friendly:
> > 
> >      coro pre_traverse(%data) {
> >          yield %data{ value };
> >          yield $_ for <&_.clone(%data{ left  })>;
> >          yield $_ for <&_.clone(%data{ right })>;
> >      }
> 
> > If I work backwards, the syntax I'd _want_ for something like that 
> > would be much like Luke proposed:
> > 
> >      sub pre_traverse(%data) is coroutine {
> >          yield %data{ value };
> >          pre_traverse( %data{ left  } );
> >          pre_traverse( %data{ right } );
> >      }
> > 
> > ... where the internal pre_traverses are yielding the _original_ 
> > pre_traverse.  Whoa, though, that doesn't really work, because you'd 
> > have to implicitly do the clone, which screws up the normal iterator 
> > case!  And I don't immediately know how to have a syntax do the right
> > thing in _both_ cases.
> > 
> > So, if I have to choose between the two, I think I'd rather iteration
> > be easy than recursion be easy.  If lines like
> > 
> >         yield $_ for <&_.clone(%data{ left  })>;
> > 
> > are too scary, we might be able to make a keyword that does that,
> > like:
> > 
> >      sub pre_traverse(%data) is coroutine {
> >          yield %data{ value };
> >          delegate pre_traverse( %data{ left  } );
> >          delegate pre_traverse( %data{ right } );
> >      }
> > 
> > Maybe.  But in truth, that seems no more intuitive than the first.
> 
> Q: Can you "yield" from a subsubroutine?
> 
> If no, then yield=>coro at compile time. I don't care much for this
> because it puts too much emphasis on remaining "in" the coroutine,
> precluding me from distributing functionality. John MacDonald has given
> several examples of this.

Agreed.  I want to be able to distribute functionality.  This is
isomorphic with recursion.

> Q: If you recurse, does it automatically create a new coro context?
> 
> If Yes:  We need a way to recurse in context. Perhaps by saying
> &_.recurse(...) ? 

Obviously, that's not what I advocate.

> If No: How do you create a new context? 

Like this:

    # countcounter(4) yields 0 0 1 0 0 1 2 3
    coro countcounter($n) {
      for 0..$n-1 -> $c {
        my $counter = coro { countcounter($c) };
        yield $_ for <$counter>;
        yield $c;
      }
    }  

Yay for objects!

The only thing declaring countcounter as a coro gets you is the
ability to use &countcounter itself as an iterator... and some
documentation.  Since it takes an argument, it would probably be just
as useful as a sub.

> > (s/coroutine/thread/g for the same rough arguments, e.g. "why should 
> > the caller care if what they're doing invokes parallelization, so
> > long as it does the right thing?")
> 
> Global variables. Threads __never__ do the right thing.

Hopefully Perl 6 will change that.

Luke

Reply via email to