Mark S. Miller (2013-06-21T06:13:12.000Z)
github at esdiscuss.org (2013-07-12T02:27:37.435Z)
> I don't see any simple and obvious path from understanding the synchronous > message send to understanding how promises work. How does that explanation > look? Take it in three steps. ## Step 1 ```js var d = a.foo(b,c); ``` This does synchronous message sending. It delivers the message `foo(b,c)` to the object designated by `a` immediately, transferring control to that object -- the callee -- now. The caller blocks waiting for the callee to respond. The callee runs to completion, finally returning a value. At this point the caller receives that value into d and continues. In order for the callee to be invoked synchronously, it must be local, since we don't want to wait on a round trip to a remote object. In a communicating event-loop system, such synchronous call/return has a strong side effect contract with pros and cons. * pros: no local time passes between the calling and the being called, so the callee gets control in the state in which the caller made the request. * cons: the callee runs while the caller, and the caller's caller, etc, are suspended in the midst of some operations. They might have suspended invariants, or otherwise be unprepared for recursive entry in their current state. This threatens both caller and callee. ## Step 2 ```js var dP = aP ! foo(b,c); ``` This does asynchronous message sending. It delivers the message `foo(b,c)` to the object designated by aP eventually, eventually causing that object -- the callee -- to gain control. But the caller proceeds now without any interleaving of control by others. Since the caller proceeds immediately, dP cannot yet provide access to what the callee will return. But it still designates that value, whatever it will be. A designator whose designation is not yet determined is a promise. If the callee eventually returns an int, then dP is already a promise for that int, though neither it nor we know that yet. Since we're only sending a message to the callee eventually and not waiting for it to respond, we don't much care whether it is local or remote. In a communicating event loop system, such asynchronous message sending has a strong side effect contract with the opposite pros and cons. * pros: The caller executes to completion without possibility of interference from the callee. Any delicate state the caller was in the midst of manipulating is unperturbed, and the caller can complete its manipulation, confident that its invariants were not disrupted. Likewise, the callee receives the message in an empty stack state, in which all previous turns have presumably restored all heap invariants. This is a robust situation from which to start running. * cons: Between the caller requesting and the callee receiving, and arbitrary number of previously queued turns may run in the meantime, changing the world from the one in which the caller decided to send the message. By the time it arrives, it may no longer be relevant or appropriate. ## Step 3 Ok, so we can `.` on local objects like `a`, and we can `!` on local or remote objects like aP. What about dP? It also designates something, but that something is separated from us in time, not (necessarily) in space. No matter! Asynchrony handles that too. If aP is remote, the message gets queued on the event-loop hosting the object aP designates. If dP is pending, the message gets queued in dP itself. Once dP knows what it designates, it forwards all these queued messages to that target using `!`.