[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