a weird yield* edge case
Erik Arvidsson
erik.arvidsson at gmail.com
Sat Jan 31 08:56:54 PST 2015
Another option would be to throw. Then the caller can tell that they did
something that was not expected by the inner iterator.
On Sat, Jan 31, 2015, 08:43 Salvador de la Puente González <
salva at unoyunodiez.com> wrote:
> From my point of view, it should do nothing if there is no throw() method
> to call. The problem you are pointing is worthy to be noted but is a
> problem for the implementer.
> El 31/01/2015 04:29, "Allen Wirfs-Brock" <allen at wirfs-brock.com> escribió:
>
> Generally, we want yield* to be as transparent as possible, so that if we
>> have a Iterable Inner and a generator defined like:
>>
>> function *wrapper() {
>> yield *Inner();
>> }
>>
>> any sequence of next/throw/return method calls on an iterator produced by
>> wrapper will generate the same results as if the same sequence of method
>> calls had been directly applied to the Inner iterator instance that is
>> wrapped.
>>
>> And this generally works (or at least will after I finish fixing some
>> bugs) if wrapper and Inner are both generators. But here is the edge case
>> where it appears impossible to achieve full transparency.
>>
>> Generators always[*] have both a "return" and "throw" method and
>> everything works transparently as expected. However, if the iterator
>> returned by Inner is not a generator object, it might not have a "throw"
>> method but still have a "return" method. Normally a "throw" to such a
>> wrapper iterator would be forwarded by yield* to the inner iterator's throw
>> method, presumably triggering any "finalization" processing needed by the
>> inner iterator. However, yield* can't forward the the throw to a
>> non-existent inner "throw" method. But the existence of a "return" method
>> is a strong hint that the inner iterator may have some "finalization" it
>> should be given an opportunity to perform.
>>
>> It seems like, there are two plausible semantics for this case, each with
>> an undesirable characteristic:
>>
>> 1) yield* doesn't invoke anything on the inner iterator in this
>> situation. Transparency is preserved, but the inner iterator may have
>> "finalization" processing that never gets executed
>> 2) yield* invokes "return" on the inner iterator in this situation.
>> Inner iterator gets a chance to run its "finalization" processing. But
>> full transparency is lost as a method is invoked on the inner iterator that
>> that would not have been invoked with the wrapper wasn't sitting in the
>> middle.
>>
>> (Note that wrapper already isn't truly transparent, because it is
>> exposing a "throw" method that doesn't exist on the iterator iterator.
>> It's possible, that the visibility of the "throw" method is what caused
>> the consumer to invoke it, rather than invoking the "return" method.)
>>
>> So, opinions on which of these alternatives is better? Are there any
>> others?
>>
>> Allen
>>
>> [*] this situation actually can occur when Inner is also a generator, but
>> it requires over-riding the 'throw' method for that generator's instance
>> with undefined.
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150131/1d6d4b06/attachment.html>
More information about the es-discuss
mailing list