develooper Front page | perl.perl6.language | Postings from May 2003

Re: Coroutine calling convention

Thread Previous | Thread Next
From:
Luke Palmer
Date:
May 5, 2003 03:01
Subject:
Re: Coroutine calling convention
Message ID:
ygcu1c9iug6.fsf@babylonia.flatirons.org
> > > So what you suggest is essentially a needless limitation.  Even
> > > perl5 coroutines (Coro and Coro::*) can do more at this point!
> > 
> > I don't quite understand.  What is limited about it?  Can you give
> > an example?
> 
> And the point being...
> 
> What you suggest looks nice, and there is very little which can be
> misunderstood in this approach.  But!  You essentially limit the
> semantics to Dan's case 1, with a possibility to explicitly achieve
> case 2 behavior (by making two `iterators').  It is not possible to
> implement case 3 at all.

(For those of you without immediate access to Dan's blog, case 1 is to
ignore arguments on subsequent calls until the function thinks it's
done, case 2 is to start a new coroutine when you call with different
arguments, and case 3 is to change already-bound arguments in the
middle of the call)

I think case 3 is so wierd (and dangerous) that it deserves a special
name.  That's why you put the coroutine in the iterator I<object>:

    my $iter = coroutine_func(1, 2, 3);
    print <$iter>;
    $iter->rebind(3, 2, 1);
    print <$iter>;

There are some other benefits of having it in an object: it's possible
to terminate it in the middle of its execution:

    $iter->terminate;
    # or
    undef $iter;  # Let GC get it

It's possible to pass it around, rather than having it manditorily
stay in one scope.  I think this is a more important benefit than
avoiding the initialization step.  It's encapsulated in the iterator
interface, so you can use it where people might expect a filehandle or
any other kind of iterator.  And finally, it makes it easy to tie to
various objects.

But then, I haven't yet seen any tolerable alternatives.  I don't
consider the semantics that Dan describes at all tolerable (despite
that being the traditional way to do it), unless there's a piece of
the interface I'm missing.

> On the other hand, if the coroutine semantics were to correspond to
> case 3, then case 1 is trivially implemented (by copying), but there
> is no way to achieve case 2 behavior.
> 
> In my opinion, the ability to implement/to choose from all three
> cases would be neat, neat, neat.  How?  Dunno.

See above :)

> Another thing which I don't like about your proposal is that it is
> too explicit, and involves a preparation/initialization step.

Obviously you haven't spent enough time with Perl 6 :)

    sub foobar() is coroutine {...}

    for <foobar> {
        # do stuff with each yielded value
    }

You don't have to put the iterator in a variable if you don't want
to.  That might turn out to be a subtle trap, eg:

    $val1 = <foobar>;
    $val2 = <foobar>;   # Starts a new instance!

But it's not really that subtle.  You typed the function's name twice,
so it will be I<started> twice.

As I scour google for uses of coroutines, they really are mostly
iterators, except they're just not implemented that way.  One is for a
"pipe" sort of mechanism (stream iterator), another for iterating
depth-first over a tree.  Another is for solving the towers of hanoi
with a recursive algorithm, which is really just iterating over
another (implicit) tree.

I'm biased, of course, because I've always felt that iterators were
underrepresented in Perl 5.  Iterators, especially generic ones, are
very useful tools, and I<the toolbox> barely supported them.  

Sorry for babbling.

Luke

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About