On Oct 15, 2012, at 1:03 AM, Shane Green firstname.lastname@example.org wrote:
Namely, all callbacks registered with a given Promise instance, receive the output of the original operation
This is somewhat tangential to the I/O loop discussion, and my hope for that discussion is that it won't involve Deferreds, or Futures, or Promises, or any other request/response callback management abstraction, because requests and responses are significantly higher level than accept() and recv() and do not belong within the same layer. The event loop ought to provide tools to experiment with event-driven abstractions so that users can use Deferreds and Promises - which are, fundamentally, perfectly interoperable, and still use standard library network protocol implementations.
What I think you were trying to say was that callback addition on Deferreds is a destructive operation; whereas your promises are (from the caller's perspective, at least) immutable. Sometimes I do think that the visibly mutable nature of Deferreds was a mistake. If I read you properly though, what you're saying is that you can do this:
promise = ... promise.then(alpha).then(beta) promise.then(gamma).then(delta)
and in yield-coroutine style this is effectively:
value = yield promise beta(yield alpha(value)) delta(yield gamma(value))
This deficiency is reasonably easy to work around with Deferreds. You can just do:
def fork(d): dprime = Deferred() def propagate(result): dprime.callback(result) return result d.addBoth(propagate) return dprime
Perhaps this function should be in Twisted; it's certainly come up a few times.
But, the fact that the original result is immediately forgotten can also be handy, because it helps the unused result get garbage collected faster, even if multiple things are hanging on to the Deferred after the initial result has been processed. And it is actually pretty unusual to want to share the same result among multiple callers (which is why this function hasn't been added to the core yet).