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

yield from a method

7 views
Skip to first unread message

Will Coleda

unread,
Dec 8, 2006, 4:00:37 PM12/8/06
to parrot-...@perl.org
Given the current :method and .yield implementations, the following code:

$ cat foo.pir
.sub main :main
$P1 = newclass 'foo'
$P2 = new 'foo'
$S1 = $P2.'bork'()
say $S1
$P3 = new 'foo'
$S1 = $P3.'bork'()
say $S1
.end

.namespace [ 'foo']
.sub bork :method
$I0 = 0
loop:
.yield($I0)
inc $I0
goto loop
.end

Generates the following output:

$ ./parrot foo.pir
0
1

Which is unsurprising given the current implementation. Is this desired
behavior, though?

I can work around this by storing an attribute on the class which keeps my
counter in the instance and then retrieving it with getattribute in the
loop, insuring that the state is pulled from the object instead of the
registers in the coroutine/method whenever the coroutine resumes.

Or we could have yield somehow be instance specific.

Regards.

Bob Rogers

unread,
Dec 8, 2006, 6:45:36 PM12/8/06
to Will Coleda, parrot-...@perl.org
From: "Will Coleda" <wi...@coleda.com>
Date: Fri, 08 Dec 2006 16:00:37 -0500

Given the current :method and .yield implementations . . .

. . .

Which is unsurprising given the current implementation. Is this desired
behavior, though?

This does not work right for nonmethods either. For normal subs, you
have to find the sub and clone it, and then use that as the Coroutine.
For methods, this would amount to creating a new method per instance,
which is absurd.

I can work around this by storing an attribute on the class which keeps my
counter in the instance and then retrieving it with getattribute in the
loop, insuring that the state is pulled from the object instead of the
registers in the coroutine/method whenever the coroutine resumes.

If you can do that, then you don't really need a Coroutine, do you? But
if you really can't do that, you might consider Parrot::Coroutine.

Or we could have yield somehow be instance specific.

The real fix is to build Coroutine on Continuation instead of Sub. That
would still require changing your method to create a Coroutine object
and (I assume) store it in the instance. But that might be what you
want in any case.

Perhaps the right thing would be clearer if you posted a fuller
example of what you are trying to do?

-- Bob Rogers
http://rgrjr.dyndns.org/

Will Coleda

unread,
Dec 8, 2006, 7:58:25 PM12/8/06
to Bob Rogers, parrot-...@perl.org

On Dec 8, 2006, at 6:45 PM, Bob Rogers wrote:

> From: "Will Coleda" <wi...@coleda.com>
> Date: Fri, 08 Dec 2006 16:00:37 -0500
>
> Given the current :method and .yield implementations . . .
>
> . . .
>
> Which is unsurprising given the current implementation. Is this
> desired
> behavior, though?
>
> This does not work right for nonmethods either. For normal subs, you
> have to find the sub and clone it, and then use that as the Coroutine.
> For methods, this would amount to creating a new method per instance,
> which is absurd.
>
> I can work around this by storing an attribute on the class
> which keeps my
> counter in the instance and then retrieving it with getattribute
> in the
> loop, insuring that the state is pulled from the object instead
> of the
> registers in the coroutine/method whenever the coroutine resumes.
>
> If you can do that, then you don't really need a Coroutine, do
> you? But
> if you really can't do that, you might consider Parrot::Coroutine.
>

True. At that point the yield is pretty useless. =)

> Or we could have yield somehow be instance specific.
>
> The real fix is to build Coroutine on Continuation instead of Sub.
> That
> would still require changing your method to create a Coroutine object
> and (I assume) store it in the instance. But that might be what you
> want in any case.
>
> Perhaps the right thing would be clearer if you posted a fuller
> example of what you are trying to do?
>
> -- Bob Rogers
> http://rgrjr.dyndns.org/
>

I'm attempting to implement the 'Range' object (and other lazy lists)
for perl6, using a coroutine to generate the next value in the range.
At the moment, all instantiations of the range object share the
coroutine for generating their value.

I don't have to use coroutines here, but if I can, I think it'll make
the implementation easier.

--
Will "Coke" Coleda
wi...@coleda.com


Bob Rogers

unread,
Dec 8, 2006, 9:36:32 PM12/8/06
to Will Coleda, parrot-...@perl.org
From: Will Coleda <wi...@coleda.com>
Date: Fri, 8 Dec 2006 19:58:25 -0500

. . .

I'm attempting to implement the 'Range' object (and other lazy lists)
for perl6, using a coroutine to generate the next value in the range.
At the moment, all instantiations of the range object share the
coroutine for generating their value.

I don't have to use coroutines here, but if I can, I think it'll make
the implementation easier.

--
Will "Coke" Coleda
wi...@coleda.com

At this point, I think your choices are:

1. Have a separate coroutine sub that the method clones and saves in
the object; or

2. Store the coroutine state explicitly in the object, and emulate
yielding in the method.

The second choice ought to be simpler, especially if (as I'm
guessing) there is only one C<yield> and the surrounding control
structures are straightforward. It also has the advantage of not
breaking if the Coroutine object API has to change when it eventually
gets fixed.

-- Bob

Allison Randal

unread,
Dec 12, 2006, 1:21:23 AM12/12/06
to Will Coleda, parrot-...@perl.org

It's assuming that methods have no state from one execution to the next,
which isn't a valid assumption once we throw coroutines into the mix.

The output does reflect the desired behavior for class methods, and I've
used it to implement a unique id generator that spans all instances of
the class. But for instance methods, it doesn't make any sense. Of
course, Parrot can't really distinguish class methods from instance
methods yet.

> I can work around this by storing an attribute on the class which keeps
> my counter in the instance and then retrieving it with getattribute in
> the loop, insuring that the state is pulled from the object instead of
> the registers in the coroutine/method whenever the coroutine resumes.

For the moment you'll need a hack something like this.

> Or we could have yield somehow be instance specific.

If we take a ruby-esque meta-model where the class is an object (in
addition to instances being objects) then the conceptually simplest way
to handle this is to make yield always be object-specific within
methods, whether the object is a class or an instance of a class.

Allison

0 new messages