[Python-ideas] Possible PEP 380 tweak
Jacob Holm
jh at improva.dk
Sat Oct 30 01:34:30 CEST 2010
On 2010-10-30 01:03, Greg Ewing wrote:
> Jacob Holm wrote:
>
>> The main thing to note is that the expression form of yield-from is
>> mostly intended to make it easier to have cofunctions that return a
>> value, and that there is a problem with reusing StopIteration for that
>> purpose.
>
> No, I don't think that's where the problem is, if I understand
> correctly which problem you're referring to. The fact that cofunctions
> as currently defined in PEP 3152 can't raise StopIteration and have it
> propagate to the caller is a problem with the use of StopIteration
> to signal the end of a cofunction.
Exactly.
> Whether the StopIteration carries
> a value or not is irrelevant.
>
It is relevant if we later want to distinguish between "return" and
"raise StopIteration".
>> And since there are no return values, there is no
>> problem with how "close" should treat them.
>
> There's no problem with that *now*, because close() is currently
> not defined as returning a value. A problem only arises if we
> try to overload close() to mean "no more data to send in, give me
> your result" as well as "bail out now and clean up". And as I
> pointed out, there are other ways of signalling end of data that
> work fine with things as they are.
>
That is what I meant. We were discussing whwther to add a new feature
to PEP 380 inspired by having "return <value>" in generators. If we
dropped "return <value>" from PEP 380 (with the intent of adding it to
PEP 3152 instead), so would the basis for the new feature. End of
discussion...
AFAICT, adding these features in a consistent way is a lot easier in the
context of PEP 3152.
>> 2) In PEP 3152, define "return <value>" in a cofunction to raise a new
>> IterationResult exception with the value.
>
> That would have to apply to *all* forms of return, not just ones
> with a value.
>
Of course.
>> <var> = (yield from <expr>).value
>>
>> have the benefit that the PEP 3152 expansion could reraise the
>> actual StopIteration as in:
>>
>> e = yield from f.__cocall__(*args, **kwargs)
>> if isinstance(e, IterationResult):
>> <var> = e.value
>> else:
>> raise e
>
> There's another way to approach this: define cofunctions so that
> 'return' in one of its forms is the only way to raise an actual
> StopIteration, and any explicitly raised StopIteration gets wrapped
> in something else, such as CoStopIteration. The expansion would
> then be
>
> try:
> result = yield from f.__cocall__(*args, **kwargs)
> except CoStopIteration as e:
> raise e.value
>
> where e.value is the original StopIteration instance.
>
> This would have the advantage of not requiring any change to
> yield-from as it stands.
>
That's just ugly... I realize it could work, but I think that makes
*both* PEPs more complex than necessary.
My suggestion is to cut/change some features from PEP 380 that are in
the way and then add them in a cleaner way to PEP 3152. This should
simplify both PEPs, at the cost of reopening some of the earlier
discussions.
- Jacob
More information about the Python-ideas
mailing list