<div dir="ltr"><div>Hi Jakob,</div><div><br></div><div>Sorry for the delayed reply.  So many things right now!</div><div dir="ltr"><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I was sometimes confused about this too: future itself does not return<br>
a Promise, but future + the following message send does. This is due<br>
to the compiler transformation explained in FutureNode. So value will<br>
not be sent to the Promise and p will hold the Promise right away and<br>
not be nil.<br></blockquote><div><br></div><div>Ah!  Sorry, you're right.  So "value" there is just to satisfy the compiler.  I guess the #future magic-trick kinda worked against its own "readability" in that specific case, huh?..  :)  (#yourself would be better form there, IMO).   </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
So, I agree that #future is confusing, but it is also much less to<br>
read than p := Promise new. Project current addDeferredUIMessage:<br>
[[... p resolveWith: ...] ifCurtailed: "or whatever we settle on" [p<br>
reject]].<br></blockquote><div><br></div><div>#future also breaks the formatter, which I use constantly and, since it has to assume the receiver might be a Morph, has to go through Project current addDeferredUIMessage:, MUCH slower than basic process #fork'ing, which is all I needed.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I don't think you ever could use Promises and values interchangeably.<br>
Promise>>wait does more or less what you want, but it means you have<br>
to use the promise explicitly, not interchangeably. You can chain<br>
promises with then:[ifRejected:], and consume the Promise outcome in<br>
the respective block argument, turning your control flow from<br>
left-to-right-top-to-down into Promise style... But just getting the<br>
value of the Promise at some point without wait might just answer nil<br>
if still unresolved.<br></blockquote><div><br></div><div>It essentially renders its #value message completely and utterly useless, since you can't discern between whether nil was the result or simply still running, without checking one of the state messages but... why?</div><div><br></div><div>That's why I overrode Promise>>#value to:</div><div><br></div><div>    ^ self wait</div><div><br></div><div>Interchangeability via #value also means that chaining "just works".  My code can always simply resolveWith: a value or a Promise of a value, and if its a Promise, the existing code chains it for me, without ever having to bring the #then: API into my code.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
About signalling errors upon #value as you put it: you mean you want<br>
to get the original Exception when you get the result of the promise,<br>
so you don't have to check in which state the promise is? It sounds<br>
useful at first, but the result or reason (for errors) can be<br>
retrieved more than once; would the exception only be signalled<br>
(again) upon the first retrieval of the result? </blockquote><div><br></div><div>Yes.  And your program's error-handling can worry about its own errors only, not having to account for BrokenPromise..</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Also it would look<br>
funny in the Debugger stack: either you put the original stack of the<br>
exception on top of the current (result getting) one, or you hide the<br>
current stack, or you cut away the sender of the exception context<br>
(which makes it less useful). Do you have an idea how to resolve this?<br></blockquote><div><br></div><div>I think you can get the original stack from the error that's signaled.  I'd welcome a better multiprocess debugging tool, for sure, it can be difficult to figure out when things don't go as expected.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Also note that you can reject a promise with something else than an<br>
Exception. It could also be some kind of error value or just a string<br>
that explains the rejection. </blockquote><div><br></div><div>Yes, but I don't use it that way, because I prefer the interchangeability.  Honestly, it brings all kinds of case-logic into the clients code.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">You would not be able to distinguish that<br>
from a regular result without type checking. </blockquote><div><br></div><div>Current Promise doesn't even have a way to ask #isPending, you always  have to check <u>both</u> terminal states (#isResolved, #isRejected) usually with a "not" in there.  Ugh.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Maybe we could have a<br>
specialized promise that only rejects on exceptions and would allow<br>
the kind of workflow you seem to have in mind where the promise is<br>
like a proxy for the result. If we determine that it is useful. :-)<br></blockquote><div><br></div><div>I did subclass Promise in the GraphQL framework to do just that and, it worked beautifully.  Took me quite a bit of mind-wrangling to finally arrive at this simplicity, all the extra stuff I didn't need really took me on a mental ride around the barnyard just to figure out I didn't need it.    :)</div><div><br></div><div>During that ride, I did notice a minor inefficiency in Promise>>#wait -- for already-resolved Promises, it could simply check isResolved before going through the Semaphore.</div><div><br></div><div>Best,</div><div>  Chris</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
</blockquote></div></div>