On Thu, Oct 27, 2011 at 1:30 PM, Greg Ewing email@example.com wrote:
On 27/10/11 15:53, Nick Coghlan wrote:
That idea doesn't work when combined with the current idea in the PEP for implicit cocall support inside cofunction definitions. Simple method calls will see "Oh, this has __cocall__" and try to treat it like a cofunction, when the underlying object is actually an ordinary callable.
That's why I've specified that the __cocall__ method can return NotImplemented to signal that the object doesn't support cocalls. When I say "implements __cocall__" I mean "has a __cocall__ method that doesn't return NotImplemented".
Ah, I missed that. Could you add a pseudocode expansion, similar to the one in PEP 343?
_make_call = True _cocall = getattr(obj, "__cocall__", None) if _cocall is not None: _cocall_result = _cocall(*args, **kwds) _make_call = _cocall_result is NotImplemented if _make_call: _result = obj(*args, **kwds) else: _result = _cocall_result
To expand on the "implicit concurrency" discussion, it's potentially worth explicitly stating a couple more points: - thread preemption can already occur between any two bytecode instructions - exceptions can already be thrown by any expression
However, you currently handwave away the question of what constitutes "some suitable form of synchronisation" when it comes to implicit cofunction invocation. With threads, you can using the locking primitives to block other threads. With explicit cocalls, you can manually inspect a block of code to ensure it doesn't contain any yield points. With implicit cocalls, how does one implement an interpreter enforced guarantee that control will not be relinquished to the scheduler within a particular block of code?
Perhaps the PEP needs a "with not codef:" construct to revert to normal calling semantics for a section of code within a coroutine? You could still explicitly yield from such a code block, but it would otherwise be the coroutine equivalent of a critical section.