This was a little confusing my apologies.
This example
(anObject eventual identityHash * 10)
I incorrectly labeled promise chaining. It’s more properly called in the literature as pipelining, where we send a follow on DNU message to anENearPromise. Let’s break it down
anObject eventual returns anENear
Sending identityHash schedules it’s EventualMessageSend, in the Vat, and reteruns anENearPromise.
Immediately following this promised send, we eventually send a * 10. This stores it’s EventualMessageSend in the ENearPromise’s pendingSends queue and returns anENearPromise #2.
This is Promise Pipelining.
In my opinion right now it is more convenient to develop in a synchronous manner in Squeak because the debugger in its current state is better suited for that. It does not support you very well with Promises, deferred UI messages, spawned processes and the like... And when some of the tools that you are used to do not support you well anymore, it does not feel good.
Yes, indeed. I’ve been thinking about this. Deep in a send tree, an exception occurs. We would like to see a stack representation of some kind. What kind?
First guess is the stack of sending contexts leading to the exceptional send. However, good Eventual Sending Style would see calling sends to eventuality send its work and exit. Therefore, it is highly likely there is no stack available.
Is it feasible to store sends leading down to the exceptional send? This is a disconnect that could seriously affect our ability to debug effectively.
So what sort of stack could we build? As this only happens when debugging, we could afford to seek the stack for the EventualMessageSend activating the immediate stack. Store the ENearPromise that corresponds to the eMsgSend’s resolver withe the eMsgSend. Then when the activating eMsgSend is found, access the promise’s pendingSends and collect the registered reactors from calls to the promise #then: / #whenResolved: / #whenRejected:. They themselves have promises with pendingSends, so a tree of future sends could be established. These should all get #smashed: from the exceptional send, once resumed into the future.
Andso, it seems to me we could struggle to produce an historical stack, but we could provide a futuristic promise tree.
I’m thinking we really need the historical stack. For example an argument is provided that fails. Where did this argument come from. We need to backup and regenerate the argument. Without a historical stack I don’t see how that works.
Therefore, I think we may need to preserve the sending contexts. What are the implications to do this? I don’t know.
🐰
On Wed, Mar 1, 2023 at 15:23, rabbit <
rabbit@callistohouse.org> wrote:
Let’s make better Turbinado Sugar for our café con leche! The #* is sent to the result promise from #identityHash’s esend. This promise’s #doesNotUnderstand: redirectMessage: of the ‘* 10’ and returns the 2nd promise. The argument to show: cannot be an eventual ref, at this time, so a then: with a reactor is required. No promise chaining will work.
(anObject eventual identityHash * 10)
then: [:codeMag |
Transcript cr;
show: ‘code order of magnitude = ‘, codeMag].
🐰
—
Have a good one; keep it, light.
Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede
:: decentralized mobile homeless solutions ::
On Wed, Mar 1, 2023 at 14:52, rabbit <rabbit@callistohouse.org> wrote:
On Wed, Mar 1, 2023 at 14:18, Jakob Reschke <jakres+squeak@gmail.com> wrote: Event-loop based UI development is usually a good strategy. It is how Windows works at the foundations... I know that this will sound rather like an argument against it for some people. ;-P
lol! Certainement! Yet they built the Midori eventual sending OS [1].
The question is whether it is convenient to program like that. All parts involved must account for the asynchronicity. It may be more convenient to just send a Smalltalk message rather than using addDeferredUiMessage: and wrapping your intent in a block, but the code that comes after that line looks different, too.
Yes indeed. The EST: Eventual Sending Style.
((an object eventual send: #identityHash)
then: [:code | code * 10])
then: [:codeMag | Transcript cr; show: ‘code order of magnitude = ‘, codeMag].
Looking into sugar, with ESqueak, where EAbstract>>#doesNotUnderstand: eventually sends the msg like a trampoline:
(anObject eventual identityHash
>>: [:code | code * 10]
>>: [:codeMag | Transcript cr; show: ‘code order of magnitude = ‘, codeMag].
Where the as yet unimplemented ENearPromise>>#>>:>>: would be
^ (self then: reactor1)
then: reactor2.
Of course instead of a block the reactor could be (an anonymous) subclass of WhenResolvedReactor and set a closure object in initialize.
Especially if you need a result/response to continue your overall computation.
I was thinking of a possible marking of a closure as #immediate to turn all eventual sending within as immediate calls.
You may be inclined to use Promises there, where you would not do that otherwise, for example.
Right.
In my opinion right now it is more convenient to develop in a synchronous manner in Squeak because the debugger in its current state is better suited for that. It does not support you very well with Promises, deferred UI messages, spawned processes and the like... And when some of the tools that you are used to do not support you well anymore, it does not feel good.
An excellent observation, Jakob! Tool support for eventual sending would be a must, specifically the debugger.
I think this exposes the coordination problem, I guess we could call it. How does one intrepid souk debug control flow among independent event processes?
Given success with these issue, does it make sense to keep eventual sending as a candidate?
Would it not allow controller / view / model interactions to be thought about clearly?
Thanks for your consideration.
🐰
Awesome! Jecel, I’m quite curious to hear your thoughts on eventual sending. EVERYBODIES thoughts, really. Is event-loop eventual sending a feasible style / function for UI development?
🐰
—
Have a good one; keep it, light.
Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede
:: decentralized mobile homeless solutions ::
On Wed, Mar 1, 2023 at 13:00, Jecel Assumpcao Jr <
jecel@merlintec.com> wrote:
David T. Lewis wrote on Tue, 28 Feb 2023 20:39:54 -0500
> In MVC, each Controller has its own Process, and those processes are
> scheduled when needed as windows are activated. In Morphic, there is
> a single UI process.
True, but misleading. Just like the VM has a single OS thread that it
multiplexes between image level processes, the single Morphic thread
pretends to run each morph in parallel at a known rate by repeated
sending #step to them.
Because we know that only when #step for one morph is finished that
#step will be sent to the next morph, we have been programming as it
morphs did not execute in parallel even though that is what the model
was supposed to be. That is why we get in trouble when things happen
outside of the GUI scheduler.
In Self you have have more than one Morphic window and each gets its own
GUI thread, but they are unlikely to share the same objects so we don't
notice the problem. You can also have multiple windows in different
machines viewing the same "world" and in that case they all share a
single GUI thread.
-- Jecel