Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg vanessa@codefrau.net wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg vanessa@codefrau.net wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, 22 Feb 2023 at 01:56, karl ramberg karlramberg@gmail.com wrote:
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg vanessa@codefrau.net wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process.
Best, Marcel ________________________________ From: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org on behalf of Eduardo Ochs eduardoochs@gmail.com Sent: Wednesday, February 22, 2023 7:17:01 AM To: The general-purpose Squeak developers list squeak-dev@lists.squeakfoundation.org Subject: Re: [squeak-dev] How do I "sleep 5"?
Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.commailto:karlramberg@gmail.com> wrote: Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.commailto:eduardoochs@gmail.com> wrote: Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.netmailto:vanessa@codefrau.net> wrote: The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.commailto:eduardoochs@gmail.com> wrote: Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev < squeak-dev@lists.squeakfoundation.org> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process.
Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel
*From:* Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org on behalf of Eduardo Ochs eduardoochs@gmail.com *Sent:* Wednesday, February 22, 2023 7:17:01 AM *To:* The general-purpose Squeak developers list < squeak-dev@lists.squeakfoundation.org> *Subject:* Re: [squeak-dev] How do I "sleep 5"?
Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, 22 Feb 2023 at 01:56, karl ramberg karlramberg@gmail.com wrote:
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg vanessa@codefrau.net wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
I’ve been watching this thread and wondering why nobody suggests the simplest answer:
[(Delay forSeconds: 5) wait. do_something] fork.
stp
--------
Stephen Travis Pope Ojai, California, USA  http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 22, 2023, at 11:16 AM, karl ramberg karlramberg@gmail.com wrote:
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org mailto:squeak-dev@lists.squeakfoundation.org> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process.
Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel From: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org mailto:squeak-dev-bounces@lists.squeakfoundation.org> on behalf of Eduardo Ochs <eduardoochs@gmail.com mailto:eduardoochs@gmail.com> Sent: Wednesday, February 22, 2023 7:17:01 AM To: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org mailto:squeak-dev@lists.squeakfoundation.org> Subject: Re: [squeak-dev] How do I "sleep 5"?
Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com mailto:karlramberg@gmail.com> wrote: Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com mailto:eduardoochs@gmail.com> wrote: Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net mailto:vanessa@codefrau.net> wrote: The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com mailto:eduardoochs@gmail.com> wrote: Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope < stephen@heaveneverywhere.com> wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer:
[(Delay forSeconds: 5) wait. do_something] fork.
stp
Stephen Travis Pope Ojai, California, USA [image: pastedGraphic.tiff] http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 22, 2023, at 11:16 AM, karl ramberg karlramberg@gmail.com wrote:
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev < squeak-dev@lists.squeakfoundation.org> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process.
Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel
*From:* Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org on behalf of Eduardo Ochs eduardoochs@gmail.com *Sent:* Wednesday, February 22, 2023 7:17:01 AM *To:* The general-purpose Squeak developers list < squeak-dev@lists.squeakfoundation.org> *Subject:* Re: [squeak-dev] How do I "sleep 5"?
Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, 22 Feb 2023 at 01:56, karl ramberg karlramberg@gmail.com wrote:
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg vanessa@codefrau.net wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs eduardoochs@gmail.com wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC…
stp
--------
Stephen Travis Pope Ojai, California, USA  http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 23, 2023, at 1:54 PM, Vanessa Freudenberg vanessa@codefrau.net wrote:
Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope <stephen@heaveneverywhere.com mailto:stephen@heaveneverywhere.com> wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer:
[(Delay forSeconds: 5) wait. do_something] fork.
stp
Stephen Travis Pope Ojai, California, USA <pastedGraphic.tiff> http://HeavenEverywhere.com http://heaveneverywhere.com/ http://FASTLabInc.com http://fastlabinc.com/ https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 22, 2023, at 11:16 AM, karl ramberg <karlramberg@gmail.com mailto:karlramberg@gmail.com> wrote:
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org mailto:squeak-dev@lists.squeakfoundation.org> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process.
Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel From: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org mailto:squeak-dev-bounces@lists.squeakfoundation.org> on behalf of Eduardo Ochs <eduardoochs@gmail.com mailto:eduardoochs@gmail.com> Sent: Wednesday, February 22, 2023 7:17:01 AM To: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org mailto:squeak-dev@lists.squeakfoundation.org> Subject: Re: [squeak-dev] How do I "sleep 5"?
Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com mailto:karlramberg@gmail.com> wrote: Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com mailto:eduardoochs@gmail.com> wrote: Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch."
sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32).
"Three ways of toggling the color of the switch:"
sm toggleState.
bl := [ sm toggleState ]. bl value.
bm target: bl. bm actionSelector: #value. bm doButtonAction.
"Two ways of toggling the switch after 1000ms:"
sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net mailto:vanessa@codefrau.net> wrote: The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com mailto:eduardoochs@gmail.com> wrote: Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
On 2023-02-23 20:14, Stephen Travis Pope wrote:
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC…
stp
Stephen Travis Pope Ojai,California, USA pastedGraphic.tiff http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 23, 2023, at 1:54 PM, Vanessa Freudenberg vanessa@codefrau.net wrote:
Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope stephen@heaveneverywhere.com wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer: [(Delay forSeconds: 5) wait. do_something] fork. stp -------- Stephen Travis Pope Ojai,California, USA <pastedGraphic.tiff> http://HeavenEverywhere.com <http://heaveneverywhere.com/> http://FASTLabInc.com <http://fastlabinc.com/> https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 22, 2023, at 11:16 AM, karl ramberg <karlramberg@gmail.com> wrote: On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org> wrote: (bm2 future: 1000) doButtonAction. Also works for objects that are not or cannot be in the world. Uses Morphic alarms when when in UI process. Ah, that's cool. I never used #future: :-) Best, Karl Best, Marcel ------------------------------------------------------------------------ *From:* Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> on behalf of Eduardo Ochs <eduardoochs@gmail.com> *Sent:* Wednesday, February 22, 2023 7:17:01 AM *To:* The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org> *Subject:* Re: [squeak-dev] How do I "sleep 5"? Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff, !See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! ! and now I can simply run this See run: [ kf := self currentHand keyboardFocus ] after: 5000. to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =) Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com> wrote: Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld. If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected. Best, Karl On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com> wrote: Hi Vanessa! Thanks! =) This works in a workspace, "Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch." sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32). "Three ways of toggling the color of the switch:" sm toggleState. bl := [ sm toggleState ]. bl value. bm target: bl. bm actionSelector: #value. bm doButtonAction. "Two ways of toggling the switch after 1000ms:" sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000. but this doesn't: bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000. What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected? Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net> wrote: The best way to do this in Morphic is with "alarms": self addAlarm: #changeKeyboardFocus after: 5000. which would execute the morph's changeKeyboardFocus method 5 seconds later. The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is). Vanessa On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com> wrote: Hi list, a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread: http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473.html My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki... ...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace, self mySleep: 5000. kf := self currentHand keyboardFocus. switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"... Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Hi Benoit --
> Nothing prevents us from replacing Morphic or redesigning it!
Well, common sense does. ;-) Unless we make this a serious discussion considering Pros and Cons, such hasty thoughts will get us nowhere. From what I have read so far, I assume, that you have no substantial experience in writing Morphic applications? I don't know. Sorry, if my conclusion offended you. Your kind of shallow call just triggered something... :-/
[...] what's stopping us from even considering that option?
Maybe because us frequent users of Squeak/Morphic have already realized that both Cuis and Pollock are just different and not inherently better? Well, I don't know about Pollock. Cuis has different goals, backwards compatibility may not be among its most important ones.
It's not that difficult to come up with something different. The first weeks might be even fun. After that, you figure out all the corner cases and start arguing about compatibility and finding balance within the existing community. It is hard work. It is easy to ignore this fact in the beginning.
Best, Marcel Am 24.02.2023 05:47:30 schrieb Benoit St-Jean via Squeak-dev squeak-dev@lists.squeakfoundation.org: Nothing prevents us from replacing Morphic or redesigning it! If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
On 2023-02-23 20:14, Stephen Travis Pope wrote:
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC…
stp
--------
Stephen Travis Pope Ojai, California, USA [pastedGraphic.tiff] http://HeavenEverywhere.com [http://HeavenEverywhere.com] http://FASTLabInc.com [http://FASTLabInc.com] https://vimeo.com/user19434036/videos [https://vimeo.com/user19434036/videos] http://heaveneverywhere.com/Reflections [http://heaveneverywhere.com/Reflections]
On Feb 23, 2023, at 1:54 PM, Vanessa Freudenberg vanessa@codefrau.net [mailto:vanessa@codefrau.net] wrote:
Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope <stephen@heaveneverywhere.com [mailto:stephen@heaveneverywhere.com]> wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer:
[(Delay forSeconds: 5) wait. do_something] fork.
stp
--------
Stephen Travis Pope Ojai, California, USA <pastedGraphic.tiff> http://HeavenEverywhere.com [http://heaveneverywhere.com/] http://FASTLabInc.com [http://fastlabinc.com/] https://vimeo.com/user19434036/videos [https://vimeo.com/user19434036/videos] http://heaveneverywhere.com/Reflections [http://heaveneverywhere.com/Reflections]
On Feb 22, 2023, at 11:16 AM, karl ramberg <karlramberg@gmail.com [mailto:karlramberg@gmail.com]> wrote:
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org [mailto:squeak-dev@lists.squeakfoundation.org]> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process. Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel From: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org]> on behalf of Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> Sent: Wednesday, February 22, 2023 7:17:01 AM To: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org [mailto:squeak-dev@lists.squeakfoundation.org]> Subject: Re: [squeak-dev] How do I "sleep 5"? Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com [mailto:karlramberg@gmail.com]> wrote:
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it.
To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch." sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32). "Three ways of toggling the color of the switch:" sm toggleState. bl := [ sm toggleState ]. bl value. bm target: bl. bm actionSelector: #value. bm doButtonAction. "Two ways of toggling the switch after 1000ms:" sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net [mailto:vanessa@codefrau.net]> wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473.... [http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....]
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On 2023-02-24 04:02, Marcel Taeumel via Squeak-dev wrote:
Well, common sense does. ;-) Unless we make this a serious discussion considering Pros and Cons, such hasty thoughts will get us nowhere. From what I have read so far, I assume, that you have no substantial experience in writing Morphic applications? I don't know. Sorry, if my conclusion offended you. Your kind of shallow call just triggered something... :-/
Perhaps I wasn't/precise clear enough : I never seriously considered replacing Morphic altogether but we must at least recognize that Morphic could get a bit cleaner. And the Squeak image too! The 6.0 Squeak image I'm looking at right now has *** 512 ** Morph subclasses ! Do we need all that stuff? I guess not. If at least we could unload packages in a *clean* manner, it would make things easier for everyone and facilitate building smaller runtime images.
I get the idea of "basic Squeak" versus "Squeak with EVERYTHING it has to offer" but from a user perspective, having 512 subclasses of Morph can be overwhelming. On the other hand, if it's not in the image, how can a user easily find that a particular morph is available and exists in a certain repository/package? If Squeak comes loaded with EVERYTHING in the image, we should at least provide an *easy* way to unload what we don't need/want/use : that's not the case right now.
Have you tried unloading EToys just for the fun of it? It should be a one click or a one-liner thing but it needs its own page of instructions on the wiki (https://wiki.squeak.org/squeak/2848). One could hear the complaints against Morphic from Cuis & Pharo and honestly recognize that there is/was a problem. Why can't we even *suggest* such a thing in Squeak without being attacked on the mailing list?
And no, I'm not offended and your conclusion/assumption was right: my Morphic experience is limited
Maybe because us frequent users of Squeak/Morphic have already realized that both Cuis and Pollock are just different and not inherently better? Well, I don't know about Pollock. Cuis has different goals, backwards compatibility may not be among its most important ones.
I think we can say goodbye to portability. Backwards compatibility (from one Squeak version to another) is a totally different thing though.
It's not that difficult to come up with something different. The first weeks might be even fun. After that, you figure out all the corner cases and start arguing about compatibility and finding balance within the existing community. It is hard work. It is easy to ignore this fact in the beginning.
Best, Marcel
Am 24.02.2023 05:47:30 schrieb Benoit St-Jean via Squeak-dev squeak-dev@lists.squeakfoundation.org:
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
On 2023-02-23 20:14, Stephen Travis Pope wrote:
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC…
stp
Stephen Travis Pope Ojai,California, USA pastedGraphic.tiff http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 23, 2023, at 1:54 PM, Vanessa Freudenberg vanessa@codefrau.net wrote:
Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope stephen@heaveneverywhere.com wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer: [(Delay forSeconds: 5) wait. do_something] fork. stp -------- Stephen Travis Pope Ojai,California, USA <pastedGraphic.tiff> http://HeavenEverywhere.com <http://heaveneverywhere.com/> http://FASTLabInc.com <http://fastlabinc.com/> https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 22, 2023, at 11:16 AM, karl ramberg <karlramberg@gmail.com> wrote: On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org> wrote: (bm2 future: 1000) doButtonAction. Also works for objects that are not or cannot be in the world. Uses Morphic alarms when when in UI process. Ah, that's cool. I never used #future: :-) Best, Karl Best, Marcel ------------------------------------------------------------------------ *From:* Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org> on behalf of Eduardo Ochs <eduardoochs@gmail.com> *Sent:* Wednesday, February 22, 2023 7:17:01 AM *To:* The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org> *Subject:* Re: [squeak-dev] How do I "sleep 5"? Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff, !See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! ! and now I can simply run this See run: [ kf := self currentHand keyboardFocus ] after: 5000. to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =) Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com> wrote: Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld. If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it. To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected. Best, Karl On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com> wrote: Hi Vanessa! Thanks! =) This works in a workspace, "Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch." sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32). "Three ways of toggling the color of the switch:" sm toggleState. bl := [ sm toggleState ]. bl value. bm target: bl. bm actionSelector: #value. bm doButtonAction. "Two ways of toggling the switch after 1000ms:" sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000. but this doesn't: bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000. What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected? Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net> wrote: The best way to do this in Morphic is with "alarms": self addAlarm: #changeKeyboardFocus after: 5000. which would execute the morph's changeKeyboardFocus method 5 seconds later. The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is). Vanessa On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com> wrote: Hi list, a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread: http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473.html My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki... ...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace, self mySleep: 5000. kf := self currentHand keyboardFocus. switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"... Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html
Changing the subject line because it is worth the discussion.
On Thu, Feb 23, 2023 at 11:47:12PM -0500, Benoit St-Jean via Squeak-dev wrote:
On 2023-02-23 20:14, Stephen Travis Pope wrote:
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC???
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
There is absolutely nothing preventing someone from developing a replacement for Morphic in Squeak. In fact, Squeak provides exactly the tools needed to support this. The key concept is that we can have different kinds of Project that can be defined and built up to support entirely new and different user interface models. Currently we think mainly of Morphic and MVC, but there is no reason at all that someone could not build something new and different.
From an engineering point of view, the key thing is that someone
can build an entirely new kind of "project" while keeping the existing MVC and Morphic worlds alive and healthy to support the new development effort.
About 10 years ago I went through the exercise of trying to bring a much earlier version Juan's Morphic3 into Squeak. http://www.squeaksource.com/SimpleMorphicSqueak/
This project was not successful, but since that time we have made great progress in cleaning up things like global variable dependencies in Morphic/MVC, and because of that I think that it would now be much easier to do this kind of work in today's Squeak.
If anyone has the interest and motivation to try building a new kind of Morphic, I would say just go ahead and do it. It will not be simple or easy but if you can build it up step by step, keeping the existing Morphic/MVC healthy to support your development work, then I see no reason that it cannot be done.
Dave
David T. Lewis wrote on Fri, 24 Feb 2023 17:48:30 -0500
On Thu, Feb 23, 2023 at 11:47:12PM -0500, Benoit St-Jean via Squeak-dev wrote:
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
There is absolutely nothing preventing someone from developing a replacement for Morphic in Squeak. In fact, Squeak provides exactly the tools needed to support this. The key concept is that we can have different kinds of Project that can be defined and built up to support entirely new and different user interface models. Currently we think mainly of Morphic and MVC, but there is no reason at all that someone could not build something new and different.
An example of an alternative GUI was Andreas Raab's "Tweak", which was used in the Croquet and Sophie projects.
http://wiki.squeak.org/squeak/3867 https://en.wikipedia.org/wiki/Tweak_programming_environment
I am not sure why this didn't become an option in the standard Squeak distribution.
Another GUI for Squeak was PenSprites implemented at Disney. It was a fraction of the size of Morphic meant for resource constrained devices. That remained internal to Disney.
About MVC and Morphic, you have to remember that Squeak was created to implement EToys. EToys projects can have several things active on the screen at the same time while MVC is about switching focus between objects on the screen as the user interacts with them. If you start a fish swimming in circles in one corner of the screen you don't want it to freeze up if you start a new drawing in another corner.
-- Jecel
Hi all --
Here is how one would start such an endeavor:
1. Begin with implementing your new GUI framework in a repository of your choice. 2. Once it is usable and you have demonstrated that with some content, tell people about it on the list to find more contributors for your project. 3. Once your GUI framework (and tools around it) is mature enough, advocate for being able to tell users in a fresh Squeak image about it and install it with a simple button click. We have done this for Git support, Refactoring tools, Squeak Inbox Talk, Auto completion, ...
After that --- projects rarely finish step 1 --- you could decide to hand over the entire project to Squeak by integrating it into the Trunk. Alternatively, one could offer special Squeak bundles that have our new GUI framework installed and ready to use. Yet, Step 3 is usually worth pursuing first.
Here is how NOT to do it: - Starting some unfinished experiment and pushing it into Trunk, hoping that other people will take care of it.
- Having a mature version of your GUI framework in regular Trunk and still developing it in your personal repository.
At the end of the day, personal time is often spent more wisely in understanding and using and improving what is already there. Feel free to start your own libraries and applications, sure. But having the goal of replacing something that is already working is rarely a good idea. Definitely unwise for something as complex as a GUI framework.
Did you know that you can implement new widget libraries on top of Morphic? - https://github.com/tom95/Pheno - https://github.com/hpi-swa/widgets
That said, we should keep on cleaning up the system to improve modularity (by untangling dependencies) to be able to unload the things you do not need for your personal projects such as EToys, MVC, MorphicExtras, ... :-)
***
What about Tweak? I think that Tweak has really good ideas in terms of event processing. Personally, I don't think that it is better than Morphic, just different. Yet, it would be nice to have a simple working version of it in Trunk, like we have with MVC. Squeak's project abstraction can handle that. Then people can more easily learn about it and we can preserve its ideas in executable form.
Best, Marcel Am 25.02.2023 01:23:16 schrieb Jecel Assumpcao Jr jecel@merlintec.com: David T. Lewis wrote on Fri, 24 Feb 2023 17:48:30 -0500
On Thu, Feb 23, 2023 at 11:47:12PM -0500, Benoit St-Jean via Squeak-dev wrote:
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
There is absolutely nothing preventing someone from developing a replacement for Morphic in Squeak. In fact, Squeak provides exactly the tools needed to support this. The key concept is that we can have different kinds of Project that can be defined and built up to support entirely new and different user interface models. Currently we think mainly of Morphic and MVC, but there is no reason at all that someone could not build something new and different.
An example of an alternative GUI was Andreas Raab's "Tweak", which was used in the Croquet and Sophie projects.
http://wiki.squeak.org/squeak/3867 https://en.wikipedia.org/wiki/Tweak_programming_environment
I am not sure why this didn't become an option in the standard Squeak distribution.
Another GUI for Squeak was PenSprites implemented at Disney. It was a fraction of the size of Morphic meant for resource constrained devices. That remained internal to Disney.
About MVC and Morphic, you have to remember that Squeak was created to implement EToys. EToys projects can have several things active on the screen at the same time while MVC is about switching focus between objects on the screen as the user interacts with them. If you start a fish swimming in circles in one corner of the screen you don't want it to freeze up if you start a new drawing in another corner.
-- Jecel
Hello Squeakers,
My reasons for wishing Morphic gone are several:
1: the mixing of view and controller, which hinders reuse and multiple viewing;
2: the poor factoring so that the base Morph class has 6 instance variables and many of the most-used Morph classes (e.g., PluggableListMorph, PluggableTextMorph) have 20 or more instance variables, leading to poor garbage collection performance for complex GUIs;
3: the thread-unsafe nature of Morphic, and
4: Morphic isn’t MVC and doesn’t use the dependency mechanism for updating, leading to poor scalability and multiple viewing.
Thank you, Marcel, for letting us know how you think we should proceed, but I was hoping that this forum was for discussing alternatives before a single individual starts coding a new system.
I’d like to propose a system like the VisualWorks “Wrapper” framework (which I admit to being co-author of [with David Leibs]), which has several advantageous features:
1: GUIs are composed of nested very simple “wrapper” objects that handle clipping, translation, scaling, etc. but are not themselves display objects;
2: Display methods support bitmaps, graphic contexts or external vector APIs as output media;
3: Models are wrapped in ApplicationModel classes making them more pluggable and reusable via a set of AspectAdaptors and ValueHolders;
4: It has a comprehensive collection of widgets;
5: It has a drag’n’drop and forms-based GUI builder; and
6: It’s been in use since the late-1980s with only minor changes.
Here’s some doc:
http://www.esug.org/data/Old/vw-tutorials/vw25/cb25.pdf%EF%BF%BC cb25 PDF Document · 2.3 MB
stp
--------
Stephen Travis Pope Ojai, California, USA  http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 26, 2023, at 1:51 AM, Marcel Taeumel via Squeak-dev squeak-dev@lists.squeakfoundation.org wrote:
Hi all --
Here is how one would start such an endeavor:
- Begin with implementing your new GUI framework in a repository of your choice.
- Once it is usable and you have demonstrated that with some content, tell people about it on the list to find more contributors for your project.
- Once your GUI framework (and tools around it) is mature enough, advocate for being able to tell users in a fresh Squeak image about it and install it with a simple button click. We have done this for Git support, Refactoring tools, Squeak Inbox Talk, Auto completion, ...
After that --- projects rarely finish step 1 --- you could decide to hand over the entire project to Squeak by integrating it into the Trunk. Alternatively, one could offer special Squeak bundles that have our new GUI framework installed and ready to use. Yet, Step 3 is usually worth pursuing first.
Here is how NOT to do it:
- Starting some unfinished experiment and pushing it into Trunk, hoping that other people will take care of it.
- Having a mature version of your GUI framework in regular Trunk and still developing it in your personal repository.
At the end of the day, personal time is often spent more wisely in understanding and using and improving what is already there. Feel free to start your own libraries and applications, sure. But having the goal of replacing something that is already working is rarely a good idea. Definitely unwise for something as complex as a GUI framework.
Did you know that you can implement new widget libraries on top of Morphic?
That said, we should keep on cleaning up the system to improve modularity (by untangling dependencies) to be able to unload the things you do not need for your personal projects such as EToys, MVC, MorphicExtras, ... :-)
What about Tweak? I think that Tweak has really good ideas in terms of event processing. Personally, I don't think that it is better than Morphic, just different. Yet, it would be nice to have a simple working version of it in Trunk, like we have with MVC. Squeak's project abstraction can handle that. Then people can more easily learn about it and we can preserve its ideas in executable form.
Best, Marcel
Am 25.02.2023 01:23:16 schrieb Jecel Assumpcao Jr jecel@merlintec.com:
David T. Lewis wrote on Fri, 24 Feb 2023 17:48:30 -0500
On Thu, Feb 23, 2023 at 11:47:12PM -0500, Benoit St-Jean via Squeak-dev wrote:
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to design Pollock for VW, what's stopping us from even considering that option?
There is absolutely nothing preventing someone from developing a replacement for Morphic in Squeak. In fact, Squeak provides exactly the tools needed to support this. The key concept is that we can have different kinds of Project that can be defined and built up to support entirely new and different user interface models. Currently we think mainly of Morphic and MVC, but there is no reason at all that someone could not build something new and different.
An example of an alternative GUI was Andreas Raab's "Tweak", which was used in the Croquet and Sophie projects.
http://wiki.squeak.org/squeak/3867 https://en.wikipedia.org/wiki/Tweak_programming_environment
I am not sure why this didn't become an option in the standard Squeak distribution.
Another GUI for Squeak was PenSprites implemented at Disney. It was a fraction of the size of Morphic meant for resource constrained devices. That remained internal to Disney.
About MVC and Morphic, you have to remember that Squeak was created to implement EToys. EToys projects can have several things active on the screen at the same time while MVC is about switching focus between objects on the screen as the user interacts with them. If you start a fish swimming in circles in one corner of the screen you don't want it to freeze up if you start a new drawing in another corner.
-- Jecel
Hi. I’d humbly suggest…
On Tue, Feb 28, 2023 at 15:36, Stephen Travis Pope stephen@heaveneverywhere.com wrote
3: the thread-unsafe nature of Morphic, and
Load ‘ESqueak.release.1’ and make the UI thread run in a Vat. Use eventual sending, not with math, but MVC component level.
4: Morphic isn’t MVC and doesn’t use the dependency mechanism for updating, leading to poor scalability and multiple viewing.
I could easily add these for dependencies to be thread safe.
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector)
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject with: anArg self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector argument: anArg) - Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject withArguments: anArgArray self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector arguments: anArgArray) Cheers!
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede • decentralized mobile homeless solutions
Or use the built in promises and consider process switching in the Scheduler to be the vat. Evenstill, eventual sending is eventual sending. It’s a whole other thing.
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Tue, Feb 28, 2023 at 16:02, rabbit rabbit@callistohouse.org wrote:
Hi. I’d humbly suggest…
On Tue, Feb 28, 2023 at 15:36, Stephen Travis Pope stephen@heaveneverywhere.com wrote
3: the thread-unsafe nature of Morphic, and
Load ‘ESqueak.release.1’ and make the UI thread run in a Vat. Use eventual sending, not with math, but MVC component level.
4: Morphic isn’t MVC and doesn’t use the dependency mechanism for updating, leading to poor scalability and multiple viewing.
I could easily add these for dependencies to be thread safe.
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject
self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector)
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject with: anArg
self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector argument: anArg)
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject withArguments: anArgArray
self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector arguments: anArgArray) Cheers!
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede • decentralized mobile homeless solutions
Great issues!
The important thing about the dependency mechanism is that it’s all within the same thread; obviously any component can choose whether to delay or queue updates, but it receives the update: message synchronously from the model (together with all other dependents). One could add aspect filtering (i.e., the dependents collection becomes a dictionary keyed by symbolic aspect) to reduce the number of updates if that becomes an issue.
As to what’s wrong with the Wrapper framework, well, it was initially called “Navigator” (this was before web browsers stole the name), and the annoying thing about debugging was the levels of nesting of wrappers, so you sometimes had to drill down several layers to find the object that was doing the real work. This applies both to model wrappers and GUI component wrappers, but one can certainly extend explorers to (e.g.,) jump to a nested visual component subclass.
The MVC framework extended all the way up to the top-level views, where it’s convenient to have separate views and controllers.
stp
--------
Stephen Travis Pope Ojai, California, USA  http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 28, 2023, at 1:14 PM, rabbit rabbit@callistohouse.org wrote:
Or use the built in promises and consider process switching in the Scheduler to be the vat. Evenstill, eventual sending is eventual sending. It’s a whole other thing.
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Tue, Feb 28, 2023 at 16:02, rabbit <rabbit@callistohouse.org mailto:rabbit@callistohouse.org> wrote:
Hi. I’d humbly suggest…
On Tue, Feb 28, 2023 at 15:36, Stephen Travis Pope <stephen@heaveneverywhere.com mailto:stephen@heaveneverywhere.com> wrote
3: the thread-unsafe nature of Morphic, and
Load ‘ESqueak.release.1’ and make the UI thread run in a Vat. Use eventual sending, not with math, but MVC component level.
4: Morphic isn’t MVC and doesn’t use the dependency mechanism for updating, leading to poor scalability and multiple viewing.
I could easily add these for dependencies to be thread safe. Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector) Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject with: anArg self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector argument: anArg)
Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject withArguments: anArgArray self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector arguments: anArgArray) Cheers!
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede • decentralized mobile homeless solutions
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Tue, Feb 28, 2023 at 16:25, Stephen Travis Pope stephen@heaveneverywhere.com wrote:
Great issues!
I’m smiling. Anticipations of the sculpting of +7.0 Wonderous Items. So very rare, the leather squeaks! Feels so good!
The important thing about the dependency mechanism is that it’s all within the same thread;
Do you mean each native thread or a Squeak green thread (Process)?
ESqueak’s Vat has a 4-range priority q, semaphore/mutex protected. These contain closures/#valuables, called Message Sends as opposed to message calls. The Vat runs a EventualProcess on the Scheduler, at priority 30. PriotityVat>>#nextPriorityMessage safely selects the next highest priority message, and evaluated it, in partial ordering, which only applies to remote sending. The local Vat’s ordering for local sends is fully ordering.
obviously any component can choose whether to delay or queue updates, but it receives the update: message synchronously from the model (together with all other dependents).
#update: could be sent eventually.
One could add aspect filtering (i.e., the dependents collection becomes a dictionary keyed by symbolic aspect) to reduce the number of updates if that becomes an issue.
This is the dictionary used in the actionSequenceMap.
🐰
As to what’s wrong with the Wrapper framework, well, it was initially called “Navigator” (this was before web browsers stole the name), and the annoying thing about debugging was the levels of nesting of wrappers, so you sometimes had to drill down several layers to find the object that was doing the real work. This applies both to model wrappers and GUI component wrappers, but one can certainly extend explorers to (e.g.,) jump to a nested visual component subclass.
The MVC framework extended all the way up to the top-level views, where it’s convenient to have separate views and controllers.
stp
Stephen Travis Pope Ojai,California, USA [pastedGraphic.tiff] http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 28, 2023, at 1:14 PM, rabbit rabbit@callistohouse.org wrote:
Or use the built in promises and consider process switching in the Scheduler to be the vat. Evenstill, eventual sending is eventual sending. It’s a whole other thing.
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Tue, Feb 28, 2023 at 16:02, rabbit rabbit@callistohouse.org wrote:
Hi. I’d humbly suggest…
On Tue, Feb 28, 2023 at 15:36, Stephen Travis Pope stephen@heaveneverywhere.com wrote
3: the thread-unsafe nature of Morphic, and
Load ‘ESqueak.release.1’ and make the UI thread run in a Vat. Use eventual sending, not with math, but MVC component level.
4: Morphic isn’t MVC and doesn’t use the dependency mechanism for updating, leading to poor scalability and multiple viewing.
I could easily add these for dependencies to be thread safe.
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject
self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector)
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject with: anArg
self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector argument: anArg)
- Object>>#ewhen: anEventSelector send: aMessageSelector to: anObject withArguments: anArgArray
self when: anEventSelector evaluate: (EventualMessageSend receiver: anObject selector: aMessageSelector arguments: anArgArray) Cheers!
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede • decentralized mobile homeless solutions
On Tue, Feb 28, 2023 at 01:25:17PM -0800, Stephen Travis Pope wrote:
The MVC framework extended all the way up to the top-level views, where it???s convenient to have separate views and controllers.
When I look at MVC and Morphic in Squeak (which thankfully is actually something that we can do, and all in the same image, woohoo!) there is one thing that stands out to me as a really interesting difference.
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.
Obviously there are historical reasons why the two frameworks were done in these two different ways, but to me this seems to me to be a rather fundamental difference in approach.
That leads me to wonder what a morphic style of interface might look like if the morphs were not directly dependent on a single UI thread.
Maybe this is what Andreas was addressing in Tweak? I really do not know. But it seems to me that both MVC and Morphic are wonderful frameworks, while each carries some baggage from the era in which it was developed.
Stephen Travis Pope is trying to encourage some discussion here. I don't think that he literally wants to go back to the original MVC framework, but if we could have some kind of "MVC" that looks and behaves like Morphic, and that maintains a better separation of models, views, and controllers, that might be a Very Good Thing.
I also suspect that if separation of model, view, and controller is a good thing, then getting rid of our Morphic dependency on a single UI thread may be a prerequisite. Without that, the concept of a "controller" does not make much sense.
Having said all this, if we imagine that each Morphic "controller" is associated with its own control Process, then the problem of synchonizing those Processes to give the appearance of smooth concurrent display on the screen is possibly quite difficult, and this very likely is the reason for the early design decision in Morphic to use a single UI thread for each Morphic world.
This is one of the many times when I wish that Andreas could be here to focus the discussion and point out the painfully obvious things that we are probably all overlooking.
Dave
On 2023-02-28, at 5:39 PM, David T. Lewis lewis@mail.msen.com wrote:
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.
That's not entirely correct so far as I can see, and certainly not what I remember. Mind you, it is about 20 years since I used an MVC project for anything.
In MVC-land there is a *new* UI process created each time a window is activated; try opening a process browser and setting it to autoupdate, then opening some general windows and moving around them.
Obviously there are historical reasons why the two frameworks were done in these two different ways, but to me this seems to me to be a rather fundamental difference in approach.
That leads me to wonder what a morphic style of interface might look like if the morphs were not directly dependent on a single UI thread.
Maybe this is what Andreas was addressing in Tweak? I really do not know. But it seems to me that both MVC and Morphic are wonderful frameworks, while each carries some baggage from the era in which it was developed.
We used Tweak in the Sophie project and it was ... painful. Very different and a total nightmare to debug in, which really made life much less pleasant.
Stephen Travis Pope is trying to encourage some discussion here. I don't think that he literally wants to go back to the original MVC framework, but if we could have some kind of "MVC" that looks and behaves like Morphic, and that maintains a better separation of models, views, and controllers, that might be a Very Good Thing.
I also suspect that if separation of model, view, and controller is a good thing, then getting rid of our Morphic dependency on a single UI thread may be a prerequisite. Without that, the concept of a "controller" does not make much sense.
One of my then and always objections to morphic was the conflation of everything into one lump; it struck me as pure laziness. It was, I think, inherited from the original Self version. Splitting out controllers allowed for different handling of inputs for the same views and models, splitting out views allowed for differing rendering of the same models. I *don't* think that requires any change to how the morphic world uses a single process though. The big problem with actually having separate processes for each window/widget/morph include the aforementioned debugging horror and the need to have resource locking absolutely everywhere. That tends to be expensive.
Note that we actually do have separate models in morphic as well, for some but not all cases. Look at the hierarchy for Model.
Where morphic has some wins is the model of a morph requesting information about whether it needs to update rather than the older update/changed model where some application model says "I changed my wibble!" and a storm of changed/update messages blasts through the system. The practical problem with that was always in making sure all the implementations coordinate well. It is terribly easy to end up with cycles that don't stop, duelling counter-updates and so on. The morphic approach avoids that at the (non-trivial) cost of checking regularly with the stepping mechanism. Ironically it (kinda) goes back to the old co-operative multitasking idiom of RISC OS, mac OS 9 and Windows 3 ;-)
But - it is simpler to explain and program and handle. We must note that the dependency is all still there in morphic as well if you want to use it. It manages to simplify even that though, by simply gathering changed notifications and making them kill the bounding rectangle, which then acts as a trigger to redraw and thereby update.
Having worked for several years with the great Mad Dog Leibs when I was managing the dept. at parcplace, building VisualWorks 1 and 2, I can say with some fervour that I hated ValueHolder then and I do now. I think it was a terrible idea that resulted in a catastrophic mental disconnect between components and the model logic. When you use a name in a way that puts it everywhere it becomes near meaningless and makes it almost impossible to follow logic through it. I had to try to unravel some recent VW code a couple of years ago and I deeply disapprove of what it has become.
If anyone wants a UI builder, well there are several in Squeak world. Try looking for vivide for example, or perhaps maui for a quite different approach.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Never test for an error condition you don't know how to handle.
Indeed a great topic!
Since I was curiously fascinated by UIs during most of my programmer life, I take the liberty to jump in from the sidelines.
UIs are one of the most complex parts of IT systems (with games as fore runners). So many different kinds of objects with so different behaviors. And they must all work together in an asynchronous fashion (unpredictable users/environment). I believe that object orientation itself was invented partly to get a grip on the complexity of UIs.
If one could start fresh... To me, layout is of central importance. Therefore, I would start with frames. Geometrical layout boxes made up of 4 sides (objects!). I would distinguish between horizontals and verticals, reducing complexity considerably. Horizontals and verticals would be connected by constraints. All (well most) widgets should know their intrinsic extend. Frames would be only responsible for layout, not for nesting or event relaying (they do create and react to events though). For example to me, a table/grid/whatever is not composed of cells, rows or columns, but of horizontal and vertical constraints on which widgets can orient themselves.
Events No polling. The more host events one can use, the better. (Is it gone is squeak?) I think that widgets should be actors with their own message queues (current hardware should be sufficient). UI elements can/should have also their own dynamic and independent behaviors. This reduces interdependencies, concurrency problems and, therefore complexity. But then you are fully in the asynchronous programming world (potentially painful paradigm shift).
There would be 'models' communicating with 'views'. I never understood controllers, I admit. To me, a view is the surface to the user and should be responsible for interpreting user events. I never had the urge to dynamically or statically replace controllers (the reason for having a separate object). For the communication, I would opt for announcements, because they can carry real objects around. Again reducing complexity.
Direct manipulation is super important! THE outstanding feature of squeak must be kept and improved/enhanced.
Of course, all this is pure fantasy - science fiction...
Happy hacking, Christian
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
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
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
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. Especially if you need a result/response to continue your overall computation. You may be inclined to use Promises there, where you would not do that otherwise, for example.
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.
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
Oops.
[1] Midori • http://joeduffyblog.com/2015/11/03/blogging-about-midori/
— 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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
In particular, Asynchronous Everything
http://joeduffyblog.com/2015/11/19/asynchronous-everything/
— 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:53, rabbit rabbit@callistohouse.org wrote:
Oops.
[1] Midori • http://joeduffyblog.com/2015/11/03/blogging-about-midori/
— 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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
Does a block closure preserve its creating context? Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
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
On Fri, 3 Mar 2023 at 07:41, Eliot Miranda eliot.miranda@gmail.com wrote:
On Mar 2, 2023, at 11:54 PM, rabbit rabbit@callistohouse.org wrote:
Does a block closure preserve its creating context?
Yes, but not the creating context’s continuation.
Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
This is a good idea and could be fine efficiently with the current VM architecture. (*) Promises would be created with the equivalent of “call-cc”, (*) scheme’s call-with-current-continuation. I’ve discussed this with Andreas, Avi Bryant, Colin Putney, and others over the years. It would elevate the level of comprehensibility in future/promise based systems significantly.
As long as "call-cc" means "delimited continuations", yup yup. (See https://okmij.org/ftp/continuations/against-callcc.html and https://okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim)
frank
Further, because the exception system is first-class, handler search could be extended from the promise’s stack to its enclosing continuation’s stack, which would make managing errors in promises much easier; one would not have to establish an error handler where each promise is created, but could establish a single error handler in the thread that creates promises (etc, this can nest if desired/so implemented).
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
(*) an implementation note for those looking fir a juicy VM project. The essence of call-cc is stack duplication. C.f. the explicit stack duplication in Seaside’s delimited continuations. When call-cc occurs effectively the entire stack is duplicated so that both the creating and the created thread can continue. (for promises this allows us to see where the promise originates long after the creating thread has continued and returned from where it created the promise, which is why this helps with debugging).
I am told that in efficient scheme implementations stack duplication is made lazy. Essentially a flag is set in an activation record that does call-cc that is checked at return time. This causes the activation to be preserved for the call-cc continuation and set for the activation record being returned into, lazily duplicating only those activations that are actually returned from. Neat.
In the Cog VM, executable activation records (contexts) live in a special form on small stack pages in the stack zone. This is done both to avoid having to create context objects until unavoidable (home contexts for blocks, reifying the contexts stack for the debugger, etc), abc to allow the JIT to optimize sends using conventional call instructions. Each stack page is large enough ti hold about 40 normal sized activations (& only one of two huge activations). Having the equivalent of call-cc duplicate the entire stack page, and propagate down the “preserve/duplicate me” flag to the next page, could be extremely efficient, avoiding the relatively expensive return-time check of scheme implementations.
Anybody seriously considering building in Squeak above Cog things like a massively parallel compute architecture, or making things like Teatime (in Croquet) much easier to debug, would do well to take such an approach.
BTW, Jecek’s explanation of the concurrency architecture in Morphic is masterful and should at least be copied into the help browser. Thank you, Jecel.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit <rabbit@callistohouse.org
:
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
Might be worth revisiting some of Tweak's ideas. That was a UI for Squeak inspired by Morphic but with much nicer coding semantics.
The thing I loved most about it was that you could write code as if it was the only thing running. It was handling concurrency behind the scenes.
Stuff like this animation:
0 to: 100 do: [ :x | object x: x. self wait: 20]
or this event handler
downEvent := object waitFor: #mouseDown. [ evt := object waitFor: #mouseMove or: #mouseUp. evt type = #mouseUp] whileFalse: [ ... do something (even blocking...) ]
(I forgot the exact syntax)
Tweak suffered from low debuggability (there were race conditions that were really hard to get right), and perceived tie-in to Croquet (even though it could be used by itself). But when it worked it was magical.
Vanessa
On Fri, Mar 3, 2023 at 8:35 AM Frank Shearar frank.shearar@gmail.com wrote:
On Fri, 3 Mar 2023 at 07:41, Eliot Miranda eliot.miranda@gmail.com wrote:
On Mar 2, 2023, at 11:54 PM, rabbit rabbit@callistohouse.org wrote:
Does a block closure preserve its creating context?
Yes, but not the creating context’s continuation.
Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
This is a good idea and could be fine efficiently with the current VM architecture. (*) Promises would be created with the equivalent of “call-cc”, (*) scheme’s call-with-current-continuation. I’ve discussed this with Andreas, Avi Bryant, Colin Putney, and others over the years. It would elevate the level of comprehensibility in future/promise based systems significantly.
As long as "call-cc" means "delimited continuations", yup yup. (See https://okmij.org/ftp/continuations/against-callcc.html and https://okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim)
frank
Further, because the exception system is first-class, handler search could be extended from the promise’s stack to its enclosing continuation’s stack, which would make managing errors in promises much easier; one would not have to establish an error handler where each promise is created, but could establish a single error handler in the thread that creates promises (etc, this can nest if desired/so implemented).
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
(*) an implementation note for those looking fir a juicy VM project. The essence of call-cc is stack duplication. C.f. the explicit stack duplication in Seaside’s delimited continuations. When call-cc occurs effectively the entire stack is duplicated so that both the creating and the created thread can continue. (for promises this allows us to see where the promise originates long after the creating thread has continued and returned from where it created the promise, which is why this helps with debugging).
I am told that in efficient scheme implementations stack duplication is made lazy. Essentially a flag is set in an activation record that does call-cc that is checked at return time. This causes the activation to be preserved for the call-cc continuation and set for the activation record being returned into, lazily duplicating only those activations that are actually returned from. Neat.
In the Cog VM, executable activation records (contexts) live in a special form on small stack pages in the stack zone. This is done both to avoid having to create context objects until unavoidable (home contexts for blocks, reifying the contexts stack for the debugger, etc), abc to allow the JIT to optimize sends using conventional call instructions. Each stack page is large enough ti hold about 40 normal sized activations (& only one of two huge activations). Having the equivalent of call-cc duplicate the entire stack page, and propagate down the “preserve/duplicate me” flag to the next page, could be extremely efficient, avoiding the relatively expensive return-time check of scheme implementations.
Anybody seriously considering building in Squeak above Cog things like a massively parallel compute architecture, or making things like Teatime (in Croquet) much easier to debug, would do well to take such an approach.
BTW, Jecek’s explanation of the concurrency architecture in Morphic is masterful and should at least be copied into the help browser. Thank you, Jecel.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit < rabbit@callistohouse.org>:
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
On Fri, Mar 3, 2023 at 14:51, Vanessa Freudenberg vanessa@codefrau.net wrote:
Might be worth revisiting some of Tweak's ideas. That was a UI for Squeak inspired by Morphic but with much nicer coding semantics.
The thing I loved most about it was that you could write code as if it was the only thing running. It was handling concurrency behind the scenes.
Vanessa, how did concurrency work behind the scenes? Do Tweak’s UI events each trigger separate activations, each it’s own Process?
Stuff like this animation:
0 to: 100 do: [ :x | object x: x. self wait: 20]
or this event handler
downEvent := object waitFor: #mouseDown. [ evt := object waitFor: #mouseMove or: #mouseUp. evt type = #mouseUp] whileFalse: [ ... do something (even blocking...) ]
I do not even know this answer but I’m extremely curious if I might use it in my Vat’s eventual promise if apropos. Does Morphic or Tweak allow for semaphore wait blocking in the UIProcess to keep the UIProcess unblocked and active, responsive? Or does the UI freeze?
🐰
(I forgot the exact syntax)
Tweak suffered from low debuggability (there were race conditions that were really hard to get right), and perceived tie-in to Croquet (even though it could be used by itself). But when it worked it was magical.
Vanessa
On Fri, Mar 3, 2023 at 8:35 AM Frank Shearar frank.shearar@gmail.com wrote:
On Fri, 3 Mar 2023 at 07:41, Eliot Miranda eliot.miranda@gmail.com wrote:
On Mar 2, 2023, at 11:54 PM, rabbit rabbit@callistohouse.org wrote:
Does a block closure preserve its creating context?
Yes, but not the creating context’s continuation.
Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
This is a good idea and could be fine efficiently with the current VM architecture. (*) Promises would be created with the equivalent of “call-cc”, (*) scheme’s call-with-current-continuation. I’ve discussed this with Andreas, Avi Bryant, Colin Putney, and others over the years. It would elevate the level of comprehensibility in future/promise based systems significantly.
As long as "call-cc" means "delimited continuations", yup yup. (See https://okmij.org/ftp/continuations/against-callcc.html and https://okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim)
frank
Further, because the exception system is first-class, handler search could be extended from the promise’s stack to its enclosing continuation’s stack, which would make managing errors in promises much easier; one would not have to establish an error handler where each promise is created, but could establish a single error handler in the thread that creates promises (etc, this can nest if desired/so implemented).
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
(*) an implementation note for those looking fir a juicy VM project. The essence of call-cc is stack duplication. C.f. the explicit stack duplication in Seaside’s delimited continuations. When call-cc occurs effectively the entire stack is duplicated so that both the creating and the created thread can continue. (for promises this allows us to see where the promise originates long after the creating thread has continued and returned from where it created the promise, which is why this helps with debugging).
I am told that in efficient scheme implementations stack duplication is made lazy. Essentially a flag is set in an activation record that does call-cc that is checked at return time. This causes the activation to be preserved for the call-cc continuation and set for the activation record being returned into, lazily duplicating only those activations that are actually returned from. Neat.
In the Cog VM, executable activation records (contexts) live in a special form on small stack pages in the stack zone. This is done both to avoid having to create context objects until unavoidable (home contexts for blocks, reifying the contexts stack for the debugger, etc), abc to allow the JIT to optimize sends using conventional call instructions. Each stack page is large enough ti hold about 40 normal sized activations (& only one of two huge activations). Having the equivalent of call-cc duplicate the entire stack page, and propagate down the “preserve/duplicate me” flag to the next page, could be extremely efficient, avoiding the relatively expensive return-time check of scheme implementations.
Anybody seriously considering building in Squeak above Cog things like a massively parallel compute architecture, or making things like Teatime (in Croquet) much easier to debug, would do well to take such an approach.
BTW, Jecek’s explanation of the concurrency architecture in Morphic is masterful and should at least be copied into the help browser. Thank you, Jecel.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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. > > 🐰 > >> Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org: >> >>> 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
On Fri, Mar 3, 2023 at 11:35, Frank Shearar frank.shearar@gmail.com wrote:
On Fri, 3 Mar 2023 at 07:41, Eliot Miranda eliot.miranda@gmail.com wrote:
On Mar 2, 2023, at 11:54 PM, rabbit rabbit@callistohouse.org wrote:
Does a block closure preserve its creating context?
Yes, but not the creating context’s continuation.
Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
This is a good idea and could be fine efficiently with the current VM architecture. (*) Promises would be created with the equivalent of “call-cc”, (*) scheme’s call-with-current-continuation. I’ve discussed this with Andreas, Avi Bryant, Colin Putney, and others over the years. It would elevate the level of comprehensibility in future/promise based systems significantly.
As long as "call-cc" means "delimited continuations", yup yup. (See https://okmij.org/ftp/continuations/against-callcc.html and https://okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim)
frank
Oh my! You’re dropping gemz! I’ll try to find time to read, especially the second. Not yet clear to me the differences between a undelimited non-function full context, versus the delimited functional context’s prefix. 🐰
Further, because the exception system is first-class, handler search could be extended from the promise’s stack to its enclosing continuation’s stack, which would make managing errors in promises much easier; one would not have to establish an error handler where each promise is created, but could establish a single error handler in the thread that creates promises (etc, this can nest if desired/so implemented).
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
(*) an implementation note for those looking fir a juicy VM project. The essence of call-cc is stack duplication. C.f. the explicit stack duplication in Seaside’s delimited continuations. When call-cc occurs effectively the entire stack is duplicated so that both the creating and the created thread can continue. (for promises this allows us to see where the promise originates long after the creating thread has continued and returned from where it created the promise, which is why this helps with debugging).
I am told that in efficient scheme implementations stack duplication is made lazy. Essentially a flag is set in an activation record that does call-cc that is checked at return time. This causes the activation to be preserved for the call-cc continuation and set for the activation record being returned into, lazily duplicating only those activations that are actually returned from. Neat.
In the Cog VM, executable activation records (contexts) live in a special form on small stack pages in the stack zone. This is done both to avoid having to create context objects until unavoidable (home contexts for blocks, reifying the contexts stack for the debugger, etc), abc to allow the JIT to optimize sends using conventional call instructions. Each stack page is large enough ti hold about 40 normal sized activations (& only one of two huge activations). Having the equivalent of call-cc duplicate the entire stack page, and propagate down the “preserve/duplicate me” flag to the next page, could be extremely efficient, avoiding the relatively expensive return-time check of scheme implementations.
Anybody seriously considering building in Squeak above Cog things like a massively parallel compute architecture, or making things like Teatime (in Croquet) much easier to debug, would do well to take such an approach.
BTW, Jecek’s explanation of the concurrency architecture in Morphic is masterful and should at least be copied into the help browser. Thank you, Jecel.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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.
🐰
> Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org: > >> 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
I am so grateful you share in my astonishment at the potential power of a promise system. C.f. seeing as how you’ve prepared the Way! I’m so bloody grateful! My dreams seem to coming true! 🙏🏻 God is good.
I’ve several questions below. 🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 10:41, Eliot Miranda eliot.miranda@gmail.com wrote:
On Mar 2, 2023, at 11:54 PM, rabbit rabbit@callistohouse.org wrote:
Does a block closure preserve its creating context?
Yes, but not the creating context’s continuation.
Would you explain the difference between a context and a continuation?
Are they to be stored by us?
How do continuations fulfill the debugger stack? Would changes to the debugger be necessary?
•••
Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
This is a good idea and could be fine efficiently with the current VM architecture. (*) Promises would be created with the equivalent of “call-cc”, (*) scheme’s call-with-current-continuation. I’ve discussed this with Andreas, Avi Bryant, Colin Putney, and others over the years. It would elevate the level of comprehensibility in future/promise based systems significantly.
Delighted! How should I go about doing this when creating a promise?
Further, because the exception system is first-class, handler search could be extended from the promise’s stack to its enclosing continuation’s stack
If I’m following you, the promise stack is the immediate call stack within a Process, while the enclosing continuation’s ‘stack’ is what and where and how and such?
, which would make managing errors in promises much easier; one would not have to establish an error handler where each promise is created, but could establish a single error handler in the thread that creates promises (etc, this can nest if desired/so implemented).
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
(*) an implementation note for those looking fir a juicy VM project. The essence of call-cc is stack duplication. C.f. the explicit stack duplication in Seaside’s delimited continuations. When call-cc occurs effectively the entire stack is duplicated so that both the creating and the created thread can continue. (for promises this allows us to see where the promise originates long after the creating thread has continued and returned from where it created the promise, which is why this helps with debugging).
I’ve too many other priorities, atm. I’m trying to get the Galaxy Object Scenario running in remote-promises. Yet I’m most curious to file away what’s needed. What VM changes are you suggesting? Support for call-cc when creating Promises or does Seaside’s delimited continuations suffice? Or are you speaking of stack zones support?
I am told that in efficient scheme implementations stack duplication is made lazy. Essentially a flag is set in an activation record that does call-cc that is checked at return time. This causes the activation to be preserved for the call-cc continuation and set for the activation record being returned into, lazily duplicating only those activations that are actually returned from. Neat.
In the Cog VM, executable activation records (contexts) live in a special form on small stack pages in the stack zone. This is done both to avoid having to create context objects until unavoidable (home contexts for blocks, reifying the contexts stack for the debugger, etc), abc to allow the JIT to optimize sends using conventional call instructions. Each stack page is large enough ti hold about 40 normal sized activations (& only one of two huge activations). Having the equivalent of call-cc duplicate the entire stack page, and propagate down the “preserve/duplicate me” flag to the next page, could be extremely efficient, avoiding the relatively expensive return-time check of scheme implementations.
Anybody seriously considering building in Squeak above Cog things like a massively parallel compute architecture, or making things like Teatime (in Croquet) much easier to debug, would do well to take such an approach.
Yes, please! Hello somebody! 🐰🙌🐿️💋🙈🤣⁉️
BTW, Jecek’s explanation of the concurrency architecture in Morphic is masterful and should at least be copied into the help browser. Thank you, Jecel.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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.
🐰
Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org:
> 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
E’s Galaxy Object Scenario •
https://www.dropbox.com/s/lq9hxd6cj55fzeo/The%20GalaxyObject%20scenario%20re...
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Sun, Mar 5, 2023 at 09:51, rabbit rabbit@callistohouse.org wrote:
I am so grateful you share in my astonishment at the potential power of a promise system. C.f. seeing as how you’ve prepared the Way! I’m so bloody grateful! My dreams seem to coming true! 🙏🏻 God is good.
I’ve several questions below. 🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 10:41, Eliot Miranda eliot.miranda@gmail.com wrote:
On Mar 2, 2023, at 11:54 PM, rabbit rabbit@callistohouse.org wrote:
Does a block closure preserve its creating context?
Yes, but not the creating context’s continuation.
Would you explain the difference between a context and a continuation?
Are they to be stored by us?
How do continuations fulfill the debugger stack? Would changes to the debugger be necessary?
•••
Walking the future tree, we could collect the back tree of creating contexts to establish an historical tree. I say tree because reactor #1 was then: immediately after causal send leading to the exception, and the promise got passed around and another belly cat sent a then: for reactor #2, both in the same promise’s pendingSends queue. Therefore the historical view of a future tree is also a tree. So the eventual debugger has a future / historical toggle. And we debug the tree and not the stack.
This is a good idea and could be fine efficiently with the current VM architecture. (*) Promises would be created with the equivalent of “call-cc”, (*) scheme’s call-with-current-continuation. I’ve discussed this with Andreas, Avi Bryant, Colin Putney, and others over the years. It would elevate the level of comprehensibility in future/promise based systems significantly.
Delighted! How should I go about doing this when creating a promise?
Further, because the exception system is first-class, handler search could be extended from the promise’s stack to its enclosing continuation’s stack
If I’m following you, the promise stack is the immediate call stack within a Process, while the enclosing continuation’s ‘stack’ is what and where and how and such?
, which would make managing errors in promises much easier; one would not have to establish an error handler where each promise is created, but could establish a single error handler in the thread that creates promises (etc, this can nest if desired/so implemented).
Yet, reactor #1 could also have been sent outside the causal send context. So we may still want to hold the causal context in the promise / eMsgSend object.
(*) an implementation note for those looking fir a juicy VM project. The essence of call-cc is stack duplication. C.f. the explicit stack duplication in Seaside’s delimited continuations. When call-cc occurs effectively the entire stack is duplicated so that both the creating and the created thread can continue. (for promises this allows us to see where the promise originates long after the creating thread has continued and returned from where it created the promise, which is why this helps with debugging).
I’ve too many other priorities, atm. I’m trying to get the Galaxy Object Scenario running in remote-promises. Yet I’m most curious to file away what’s needed. What VM changes are you suggesting? Support for call-cc when creating Promises or does Seaside’s delimited continuations suffice? Or are you speaking of stack zones support?
I am told that in efficient scheme implementations stack duplication is made lazy. Essentially a flag is set in an activation record that does call-cc that is checked at return time. This causes the activation to be preserved for the call-cc continuation and set for the activation record being returned into, lazily duplicating only those activations that are actually returned from. Neat.
In the Cog VM, executable activation records (contexts) live in a special form on small stack pages in the stack zone. This is done both to avoid having to create context objects until unavoidable (home contexts for blocks, reifying the contexts stack for the debugger, etc), abc to allow the JIT to optimize sends using conventional call instructions. Each stack page is large enough ti hold about 40 normal sized activations (& only one of two huge activations). Having the equivalent of call-cc duplicate the entire stack page, and propagate down the “preserve/duplicate me” flag to the next page, could be extremely efficient, avoiding the relatively expensive return-time check of scheme implementations.
Anybody seriously considering building in Squeak above Cog things like a massively parallel compute architecture, or making things like Teatime (in Croquet) much easier to debug, would do well to take such an approach.
Yes, please! Hello somebody! 🐰🙌🐿️💋🙈🤣⁉️
BTW, Jecek’s explanation of the concurrency architecture in Morphic is masterful and should at least be copied into the help browser. Thank you, Jecel.
🐰
— Have a good one; keep it, light. Kindly, rabbit . .. … ‘…^,^ 🐇🐇🐇
Sent from Callisto House mobile - Ganymede :: decentralized mobile homeless solutions ::
On Fri, Mar 3, 2023 at 02:42, rabbit rabbit@callistohouse.org wrote:
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.
🐰
> Am Mi., 1. März 2023 um 19:40 Uhr schrieb rabbit rabbit@callistohouse.org: > >> 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
What would you say didn't work well with Wrapper? What would you change/fix now? And would you keep the old dependency mechanism or use announcements?
On 2023-02-28 15:36, Stephen Travis Pope wrote:
Hello Squeakers,
My reasons for wishing Morphic gone are several:
1: the mixing of view and controller, which hinders reuse and multiple viewing;
2: the poor factoring so that the base Morph class has 6 instance variables and many of the most-used Morph classes (e.g., PluggableListMorph, PluggableTextMorph) have 20 or more instance variables, leading to poor garbage collection performance for complex GUIs;
3: the thread-unsafe nature of Morphic, and
4: Morphic isn’t MVC and doesn’t use the dependency mechanism for updating, leading to poor scalability and multiple viewing.
Thank you, Marcel, for letting us know how you think we should proceed, but I was hoping that this forum was for discussing alternatives before a single individual starts coding a new system.
I’d like to propose a system like the VisualWorks “Wrapper” framework (which I admit to being co-author of [with David Leibs]), which has several advantageous features:
1: GUIs are composed of nested very simple “wrapper” objects that handle clipping, translation, scaling, etc. but are not themselves display objects;
2: Display methods support bitmaps, graphic contexts or external vector APIs as output media;
3: Models are wrapped in ApplicationModel classes making them more pluggable and reusable via a set of AspectAdaptors and ValueHolders;
4: It has a comprehensive collection of widgets;
5: It has a drag’n’drop and forms-based GUI builder; and
6: It’s been in use since the late-1980s with only minor changes.
Here’s some doc:
preview.png cb25 http://www.esug.org/data/Old/vw-tutorials/vw25/cb25.pdf PDF Document · 2.3 MB http://www.esug.org/data/Old/vw-tutorials/vw25/cb25.pdf
http://www.esug.org/data/Old/vw-tutorials/vw25/cb25.pdf
stp
Stephen Travis Pope Ojai,California, USA pastedGraphic.tiff http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 26, 2023, at 1:51 AM, Marcel Taeumel via Squeak-dev squeak-dev@lists.squeakfoundation.org wrote:
Hi all --
Here is how one would start such an endeavor:
- Begin with implementing your new GUI framework in a repository of
your choice. 2. Once it is usable and you have demonstrated that with some content, tell people about it on the list to find more contributors for your project. 3. Once your GUI framework (and tools around it) is mature enough, advocate for being able to tell users in a fresh Squeak image about it and install it with a simple button click. We have done this for Git support, Refactoring tools, Squeak Inbox Talk, Auto completion, ...
After that --- projects rarely finish step 1 --- you could decide to hand over the entire project to Squeak by integrating it into the Trunk. Alternatively, one could offer special Squeak bundles that have our new GUI framework installed and ready to use. Yet, Step 3 is usually worth pursuing first.
Here is how NOT to do it:
- Starting some unfinished experiment and pushing it into Trunk,
hoping that other people will take care of it.
- Having a mature version of your GUI framework in regular Trunk and
still developing it in your personal repository.
At the end of the day, personal time is often spent more wisely in understanding and using and improving what is already there. Feel free to start your own libraries and applications, sure. But having the goal of replacing something that is already working is rarely a good idea. Definitely unwise for something as complex as a GUI framework.
Did you know that you can implement new widget libraries on top of Morphic?
That said, we should keep on cleaning up the system to improve modularity (by untangling dependencies) to be able to unload the things you do not need for your personal projects such as EToys, MVC, MorphicExtras, ... :-)
What about Tweak? I think that Tweak has really good ideas in terms of event processing. Personally, I don't think that it is better than Morphic, just different. Yet, it would be nice to have a simple working version of it in Trunk, like we have with MVC. Squeak's project abstraction can handle that. Then people can more easily learn about it and we can preserve its ideas in executable form.
Best, Marcel
Am 25.02.2023 01:23:16 schrieb Jecel Assumpcao Jr jecel@merlintec.com:
David T. Lewis wrote on Fri, 24 Feb 2023 17:48:30 -0500
On Thu, Feb 23, 2023 at 11:47:12PM -0500, Benoit St-Jean via
Squeak-dev wrote:
Nothing prevents us from replacing Morphic or redesigning it!
If Juan was able to do it for Cuis and Sam Shuster was able to
design
Pollock for VW, what's stopping us from even considering that
option?
There is absolutely nothing preventing someone from developing a replacement for Morphic in Squeak. In fact, Squeak provides exactly the tools needed to support this. The key concept is that we can have different kinds of Project that can be defined and built up to support entirely new and different user interface models. Currently we think mainly of Morphic and MVC, but there is no reason at all that someone could not build something new and different.
An example of an alternative GUI was Andreas Raab's "Tweak", which was used in the Croquet and Sophie projects.
http://wiki.squeak.org/squeak/3867 https://en.wikipedia.org/wiki/Tweak_programming_environment
I am not sure why this didn't become an option in the standard Squeak distribution.
Another GUI for Squeak was PenSprites implemented at Disney. It was a fraction of the size of Morphic meant for resource constrained devices. That remained internal to Disney.
About MVC and Morphic, you have to remember that Squeak was created to implement EToys. EToys projects can have several things active on the screen at the same time while MVC is about switching focus between objects on the screen as the user interacts with them. If you start a fish swimming in circles in one corner of the screen you don't want it to freeze up if you start a new drawing in another corner.
-- Jecel
Hi Stephen --
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC…
To you? Maybe. Fortunately, us frequent users of and contributors to Squeak/Morphic see this a bit differently. ;-)
I’ve been watching this thread and wondering why nobody suggests the simplest answer: [...]
First, counting the number of characters, your suggestion has more compared to using #future:. ;-) Second, I am not quite sure how you define "simplest", but using #fork comes with *a lot* of semantic baggage. One might encounter all kinds of nasty debuggers just because one does not know about the challenges of multi-processing and shared data structures and so on. Just because ST-80 MVC did not even try to support you in this regard does not imply that it is better compared to Morphic. At least, Morphic gives you something to work with.
It is so funny how people react to things they do not yet know much about. Many times, they are kind of anxious and claim to know better without even trying to learn about that unfamiliar territory. Jumping to conclusions ... so many times ... just jumping to conclusions. It is exhausting.
In general, I am always interested in discussing and improving the challenging parts in Squeak, including Morphic. However, if somebody thinks that "replacing everything" can make things better, that somebody deliberately chose to not participate in such a discussion any longer.
Guess what? Nothing is perfect. Try to look for the nice things. It may even brighten up your day a little bit. ;-)
Best, Marcel Am 24.02.2023 02:14:46 schrieb Stephen Travis Pope stephen@heaveneverywhere.com:
Sounds like yet another reason to drop morphic, if you ask me, and go back to good-old MVC…
stp
--------
Stephen Travis Pope Ojai, California, USA [pastedGraphic.tiff] http://HeavenEverywhere.com http://FASTLabInc.com https://vimeo.com/user19434036/videos http://heaveneverywhere.com/Reflections
On Feb 23, 2023, at 1:54 PM, Vanessa Freudenberg vanessa@codefrau.net wrote:
Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope <stephen@heaveneverywhere.com [mailto:stephen@heaveneverywhere.com]> wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer:
[(Delay forSeconds: 5) wait. do_something] fork.
stp
--------
Stephen Travis Pope Ojai, California, USA <pastedGraphic.tiff> http://HeavenEverywhere.com [http://heaveneverywhere.com/] http://FASTLabInc.com [http://fastlabinc.com/] https://vimeo.com/user19434036/videos [https://vimeo.com/user19434036/videos] http://heaveneverywhere.com/Reflections [http://heaveneverywhere.com/Reflections]
On Feb 22, 2023, at 11:16 AM, karl ramberg <karlramberg@gmail.com [mailto:karlramberg@gmail.com]> wrote:
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org [mailto:squeak-dev@lists.squeakfoundation.org]> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process. Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel From: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org]> on behalf of Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> Sent: Wednesday, February 22, 2023 7:17:01 AM To: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org [mailto:squeak-dev@lists.squeakfoundation.org]> Subject: Re: [squeak-dev] How do I "sleep 5"? Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com [mailto:karlramberg@gmail.com]> wrote:
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it.
To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch." sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32). "Three ways of toggling the color of the switch:" sm toggleState. bl := [ sm toggleState ]. bl value. bm target: bl. bm actionSelector: #value. bm doButtonAction. "Two ways of toggling the switch after 1000ms:" sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net [mailto:vanessa@codefrau.net]> wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473.... [http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....]
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
Hi Vanessa --
Thanks for the explanation. :-)
Behind the scenes, Morphic alarms make use of a shared queue to synchronize back into the UI process. MVC has this as well:
MorphicProject >> #addDeferredUIMessage: MVCProject >> #addDeferredUIMessage:
So, what you would do if you would want to use #fork at some point is this:
| currentProject | currentProject := Project current. [ 5 seconds wait. currentProject addDeferredUIMessage: [ "do_something" ] ] fork.
Luckily, years ago, we fixed some scheduling-related issues so that a regular #fork from within Morphic's UI process should work without #addDeferredUIMessage: as well. That is, a simple #fork will create a process with the same priority as the Morphic UI process (here: 40). And after the 5-second delay fires, that forked process will be scheduled to run the next time Morphic's main loop has finished its current cycle (see: WorldState >> #doOneCycleFor:), which means that chances are good that your forked code will not disrupt anything in Morphic:
[ 5 seconds wait. "do_something" ] fork. "40 -> Project current uiProcess priority"
[ 5 seconds wait. "do_something" ] forkAt: Project current uiProcess priority.
Yet, I would not consider this idiomatic Morphic code. Also it does not work if preemption would yield that (UI) process, which would be the case for that firing delay if:
Smalltalk processPreemptionYields.
By default, process preemption does not yield, which means that no delay can "interrupt" (or interfere with) Morphic's UI process.
Best, Marcel Am 23.02.2023 22:55:07 schrieb Vanessa Freudenberg vanessa@codefrau.net: Because Morphic is not multi-thread-clean, you have to be really careful how to write the do_something to be reliably executed from a different process. You have to coordinate with the UI process. In which case it actually becomes simpler to just stay in the UI process and use the mechanisms available.
Vanessa
On Thu, Feb 23, 2023 at 11:38 AM Stephen Travis Pope <stephen@heaveneverywhere.com [mailto:stephen@heaveneverywhere.com]> wrote:
I’ve been watching this thread and wondering why nobody suggests the simplest answer:
[(Delay forSeconds: 5) wait. do_something] fork.
stp
--------
Stephen Travis Pope Ojai, California, USA [pastedGraphic.tiff] http://HeavenEverywhere.com [http://HeavenEverywhere.com] http://FASTLabInc.com [http://FASTLabInc.com] https://vimeo.com/user19434036/videos [https://vimeo.com/user19434036/videos] http://heaveneverywhere.com/Reflections [http://heaveneverywhere.com/Reflections]
On Feb 22, 2023, at 11:16 AM, karl ramberg <karlramberg@gmail.com [mailto:karlramberg@gmail.com]> wrote:
On Wed, Feb 22, 2023 at 8:47 AM Taeumel, Marcel via Squeak-dev <squeak-dev@lists.squeakfoundation.org [mailto:squeak-dev@lists.squeakfoundation.org]> wrote:
(bm2 future: 1000) doButtonAction.
Also works for objects that are not or cannot be in the world.
Uses Morphic alarms when when in UI process. Ah, that's cool. I never used #future: :-)
Best, Karl
Best, Marcel From: Squeak-dev <squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org]> on behalf of Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> Sent: Wednesday, February 22, 2023 7:17:01 AM To: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org [mailto:squeak-dev@lists.squeakfoundation.org]> Subject: Re: [squeak-dev] How do I "sleep 5"? Hi Karl! Fantastic, thanks! =) I added this to the class in which I'm putting most of my stuff,
!See class methodsFor: 'as yet unclassified' stamp: 'Edrx 2/22/2023 02:54'! run: aBlock after: ms | aButton | aButton := SimpleButtonMorph new. aButton openInWorld; hide; target: aBlock; actionSelector: #value; addAlarm: #doButtonAction after: ms. ! !
and now I can simply run this
See run: [ kf := self currentHand keyboardFocus ] after: 5000.
to save into the variable kf the morph on which the keyboard focus is after 5 seconds. Neat! =)
Cheers, Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On Wed, 22 Feb 2023 at 01:56, karl ramberg <karlramberg@gmail.com [mailto:karlramberg@gmail.com]> wrote:
Hi, A morph has to be in the world to be able to interact with it; eg. #openInWorld.
If you don't want to see the morph you can send it message #hide. It makes the morph invisible but it's still in the world and can interact with it.
To see the morph again send #show. To delete the morph send #delete. The morph will be garbage collected.
Best, Karl
On Tue, Feb 21, 2023 at 11:57 PM Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> wrote:
Hi Vanessa! Thanks! =) This works in a workspace,
"Create a SimpleSwitchMorph with label 'Toggle' and a SimpleButtonMorph with label 'Flash'. The button will be placed below the switch." sm := SimpleSwitchMorph new. sm openInWorld. bm := SimpleButtonMorph new. bm openInWorld. bm position: bm position + (0@32). "Three ways of toggling the color of the switch:" sm toggleState. bl := [ sm toggleState ]. bl value. bm target: bl. bm actionSelector: #value. bm doButtonAction. "Two ways of toggling the switch after 1000ms:" sm addAlarm: #toggleState after: 1000. bm addAlarm: #doButtonAction after: 1000.
but this doesn't:
bm2 := SimpleButtonMorph new. bm2 target: bl. bm2 actionSelector: #value. bm2 addAlarm: #doButtonAction after: 1000.
What is the right way to add an alarm to a morph that is not shown on the screen? Also, can I create a new invisible morph every time that I want to run an alarm? Are they going to be garbage collected?
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
On Tue, 21 Feb 2023 at 02:16, Vanessa Freudenberg <vanessa@codefrau.net [mailto:vanessa@codefrau.net]> wrote:
The best way to do this in Morphic is with "alarms":
self addAlarm: #changeKeyboardFocus after: 5000.
which would execute the morph's changeKeyboardFocus method 5 seconds later.
The way of sleeping you suggest is possible too but more tricky, since you would have to move your wait code to an extra process to not block the UI process, but then make sure that the actual work is done in the UI process again (Morphic is not multithreaded, although Squeak is).
Vanessa
On Mon, Feb 20, 2023 at 8:49 PM Eduardo Ochs <eduardoochs@gmail.com [mailto:eduardoochs@gmail.com]> wrote:
Hi list,
a few days ago I asked for help on how to send a "synthetic" keyboard event to a morph, and Karl Ramberg gave me exactly the right hints in this thread:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473.... [http://lists.squeakfoundation.org/pipermail/squeak-dev/2023-February/223473....]
My code is ready except for documentation and comments - I'll work on that in the next few days and then post the result here and on the wiki...
...but there's a feature that I want to add to it that - again =( - needs something that I'm not being able to discover by myself. How do I write a line of code that waits for 5 seconds, sort of like running "sleep 5" in a shell, and that doesn't block the rest of the system? If I have that I'll be able to run these two lines in a workspace,
self mySleep: 5000. kf := self currentHand keyboardFocus.
switch the keyboard focus to something else by clicking on it, and then the variable kf will be set to this "something else"...
Thanks in advance! Eduardo Ochs http://anggtwu.net/eev-squeak.html [http://anggtwu.net/eev-squeak.html]
squeak-dev@lists.squeakfoundation.org