yield and new : SpiderMonkey and the draft Spec
Dmitry A. Soshnikov
dmitry.soshnikov at gmail.com
Tue Mar 15 12:56:45 PDT 2011
On 15.03.2011 21:13, John J. Barton wrote:
> On 11:59 AM, Dmitry A. Soshnikov wrote:
>> Moreover, forgot to mention. Passing the generator function
>> ("g-function" and "g-object" for shortness) as an argument for the
>> `Generator` constructor is not good for dynamically bound `this`
>> value (notice, that in Python's `self` is just a casual
>> variable/argument, which should be passed manually anyway).
>>
>> I.e. we should have `this` as `foo` in the following example:
>>
>> let foo = {
>> bar: function () {
>> yield (this == foo);
>> }
>> };
>>
>> let g = new Generator(foo.bar);
>> g.next(); // false
> g.next.apply(foo,[]); // true
No, here you set `this` value of the `next` activation, not for the
context of the continuation. Notice, the state of the CC's (current
continuation) context is set only once -- at it's creation. The creation
is done (by the strawman spec) at _first_ call to `next` method. In this
creation of the CC's context, `this` value is taken from the g-object
itself (and g-object got it when was created by the call to the g-function).
Currently (in non-standardized version in SpiderMonkey), `next` method
in every single/next call doesn't change `this` value of the CC's
context, since as said, uses the same context passing it around.
I don't see currently the case when the `this` value should/could be
changed in every next entering for yielding (in other case it reminds me
Python again when you can change `self` in runtime).
So all you've done with `g.next.apply(foo,[]);` is just provided `this`
value as `foo` for the `next` method. And which is caused an exception
since `next` method is applied not for a generator object, but for the
`foo`:
g.next.apply(foo, []); // not true, but TypeError
Side note: Notice though, that current SpiderMonkey 1.8.5 shows the
following exception message: "TypeError: Generator.prototype.next called
on incompatible Object". However, `Generator` binding is not defined. So
it's good either to make `Generator` binding available, or to change the
error message. Note: it's not `Generator` function used in the previous
example, it's a built-in generators constructor:
console.log(typeof Generator); // "undefined"
let g = (function () {yield}()).next.call(null); // TypeError:
Generator.prototype.next called on incompatible global
>>
>> However,
>>
>> let g = foo.bar();
>> g.next(); // true
> Could you please explain the reasoning here? I can't figure it out. To
> me, g.next() has to mean that in "next", this===g.
Yes, absolutely correct. And it does mean exactly this.
However, I was talking about `this` value of the _CC's context_ (not of
the `next`s context). Perhaps it can be convenient to have a g-function
as a method of an object and use `this` as that object during all
reenters to that continuation.
> I can't see a path to conclude that foo is involved.
Well, I can assume this (especially if a programmer isn't so familiar
with such a style of creating of these coroutines-generators). However,
if the programmer is familiar with that, then the information how `foo`
is involved here is taken from the code of the creation of the `g` -- at
the moment of g-function activation, i.e. when `this` value is provided
by the caller.
> It's only role is to hold the property 'bar' which is a function
> constructing 'g'.
>
As is said, we can't say exactly whether it's the only its purpose,
repeat, it's likely that `this` value normally can be used inside the
code of the g-function and refer to the needed object.
The other thing is mutable over the reentering the CC `this` value. E.g.
when we pass it to `next` and `next` then pass it throw to the CC's
context. Thus, we can't have different `this` value in every next call
to CC. But it breaks some existing scheme, e.g. with the same checking
of the `this` to be exactly the generator object in the `next` method.
And I'm not sure whether different `this` value is needed in different
reenters to the CC. Moreover, if to consider such coroutines as threads,
then I guess `this` value should be the same during the whole code of
the g-function body.
>>
>> But I don't see a big need in such a wrapper. If the rules are
>> specified, there should be no any confusion with using call
>> expression for getting g-object, and then use `next` to executed the
>> continuation.
> Perhaps we need a little user testing to see whose claims hold up.
>
Maybe, I'm not against it and opened to different styles and variants,
though, as I mentioned, this thing that such a generators way seems to
you unfamiliar can be just a matter of a habit.
Dmitry.
More information about the es-discuss
mailing list