<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Oct 15, 2012, at 1:03 AM, Shane Green <<a href="mailto:shane@umbrellacode.com">shane@umbrellacode.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span style="font-family: Menlo; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none; ">Namely, all callbacks registered with a given Promise instance, receive the output of the original operation</span></blockquote></div><br><div>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 <i>significantly</i> 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.</div><div><br></div><div>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:</div><div><br></div><div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">promise = ...</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">promise.then(alpha).then(beta)</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">promise.then(gamma).then(delta)</blockquote><br></div><div>and in yield-coroutine style this is effectively:</div><div><br></div><div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">value = yield promise</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">beta(yield alpha(value))</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">delta(yield gamma(value))</blockquote></div><div><br></div><div>This deficiency is reasonably easy to work around with Deferreds.  You can just do:<br><br></div><div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"><div>def fork(d):</div><div>    dprime = Deferred()</div><div>    def propagate(result):</div><div>        dprime.callback(result)</div><div>        return result</div><div>    d.addBoth(propagate)</div><div>    return dprime</div></blockquote><div><br></div><div>and then:</div><br><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"><div>fork(x).addCallback(alpha).addCallback(beta)</div><div>fork(x).addCallback(gamma).addCallback(delta)</div></blockquote><br></div><div>Perhaps this function should be in Twisted; it's certainly come up a few times.</div><div><br></div><div>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).</div><div><br></div><div>-glyph</div></body></html>