[Cuis-dev] Animator class>>composedActionExample2 crashes the VM
Szabolcs Komáromi
cuis at mnqpr.com
Mon Oct 2 13:03:17 PDT 2023
Thanks for the explanation! I needed a few days to grok it. Now I can reproduce the bug in a very simple class and also prevent it. I have a copy of Structure & Interpretation of Programming Languages and it is on my reading list, but I was a little bit lazy to read it. :)
Thanks again!
Regards,
Szabolcs
On Thu, Sep 28, 2023, at 23:57, ken.dickey at whidbey.com wrote:
> On 2023-09-28 13:06, Szabolcs Komáromi via Cuis-dev wrote:
>
> > I need little bit more context to fully grasp the problem.
>
> It is subtle. The crux is to know which closure captured values are
> shared and which are unique.
>
> The original code had an #action method that returned a closure which
> captured a reference to the `action` instance variable. So each
> invocation of the closure got a value from the `action` ivar.
>
> In the #composedActionExample2 method, there is code to assign a new
> composite closure which contains code to invoke both the new and the
> original action-closures.
>
> So when the composed action-closure is invoked, it does the new action
> and then invokes the "original" action-closure which gets the value from
> the action-ivar which _now_ contains the new, composite closure. This
> closure invokes the new action and then invokes the second, "original"
> closure which goes back to the ivar for its value, gets the composite
> closure which... recurses a lot until it runs out of stack space.
>
> By introducing a local variable into closure result of the #action
> method, the composite closure then is invoked with the new action, then
> the original action. The "original" action now returns the closed over
> local (cached) closure and does NOT go to the ivar named #action, so the
> expected result it achieved -- each action-closure is invoked only once.
> Whew! :)
>
> > Is there any recommended book/paper about BlockClosures in the Squeak
> > family of Smalltalk dialects? Are the Blue Book or the Inside Smalltalk
> > still relevant in this question?
>
> My recollection is that early Smalltalks had Block Contexts, NOT
> Closures, so I expect the Blue Book would be unhelpful in this case. I
> would expect Scheme would be more helpful (e.g. Structure &
> Interpretation of Programming Languages) if Wikipedia is too opaque.
>
> The crux is when closure captured values are shared and when they are
> unique.
>
> A couple of interesting use-cases:
>
> In Morphic-Games-Solitare, $CardTableMorph>>slide:to:nSteps:delay:next:
> moves a card from one location to another. It uses closures to capture
> position information.
>
> vvv===vvv===vvv===vvv
> slide: aMorph
> to: endPoint
> nSteps: numSteps
> delay: milliSecondsDelay
> next: nextAction
>
> "Slide from current to new position -- in owner's coordinates"
> "Nota Bene: Asynchronous. When complete, nextAction value"
>
> | startPoint delta stepCount |
> startPoint
aMorph morphPosition.
> delta
(endPoint - startPoint) / numSteps.
> stepCount := 0.
> aMorph when: #morphicStep
> evaluate: [ :ignoredArgument |
> stepCount := stepCount + 1.
> (stepCount < numSteps)
> ifTrue: [
> aMorph morphPosition:
> (startPoint + (stepCount * delta)) rounded;
> redrawNeeded
> ]
> ifFalse: [ "done"
> aMorph stopStepping.
> aMorph morphPosition: endPoint.
> aMorph removeActionsForEvent: #morphicStep.
> nextAction value
> ]
> ].
> aMorph startSteppingStepTime: milliSecondsDelay
> ^^^===^^^===^^^===^^^
>
> CardTableMorph>>addingCardOrCards:toContainer: uses closures to
> capture/remember undo actions.
>
> vvv===vvv===vvv===vvv
> addingCardOrCards: cardMorph toContainer: cardContainer
>
> "Container is about to add a Card or Cards. Remember undo action."
>
> | startContainer |
> startContainer := cardMorph valueOfProperty: #moveStart.
> cardMorph removeProperty: #moveStart.
> ((self inUndo) or: [startContainer = cardContainer ])
> ifFalse: [
> self pushUndoObject:
> [ :table :nextAction |
> table animateMoveFrom: cardContainer
> to: startContainer
> moving: cardMorph
> next: nextAction ]
> ]
> ^^^===^^^===^^^===^^^
>
> So it is worthwhile to learn about closures (IMHO).
>
> HTH,
> -KenD
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20231002/f0e6f729/attachment.htm>
More information about the Cuis-dev
mailing list