[Cuis] [SOLVED] Re: Copy vs Clone
Juan Vuletich
juan at jvuletich.org
Fri May 15 08:19:43 CDT 2015
Hi Ken,
On 5/14/2015 11:23 AM, Ken.Dickey wrote:
> On Thu, 14 May 2015 11:03:29 -0300
> Juan Vuletich<juan at jvuletich.org> wrote:
>
>
>>> The original Object>>copy would work where I implement postCopy to set location to a new MorphicTranslation.
>>>
>>> Object>>copy
>>> ^self shallowCopy postCopy
>> But the problem with this is that the original and the copy would share
>> that state embedded in the closure... They would also share submorphs, etc.
> In this case, that is the desired outcome.
Then, in this class, it is appropriate to have the same implamemtation
as in Object. Like, for example, SortedCollection.
>> Can you help me reproduce the problem with the closure? I think the best
>> would be to make that closure a "clean" one, storing any needed state in
>> the morph (maybe as properties), and accessing it via messages to self...
> Hmmm.. I'll have to send you the image.
>
> I have things taken apart and a bunch of parts all over the floor.. I have yet to comstruct a clean change-set.
>
>
>> Sometimes I think it would be nicer if all closures were clean. I'm not
>> really sure what would we lose with such restriction...
> I think you are tired. You would lose _closures_!
>
Well, I took a look at the image you sent me (btw, neat stuff!). My
point is that usually we don't really need closures:
a) For control flow, all we need is code blocks. The compiler knows
that, and optimizes most cases, avoiding the creation of a real closure.
These are never serialized by themselves (maybe the complete method is
serialized).
b) Real closures. Used for new control structures, that the compiler
doesn't know about. Also used for functional programming and
continuations. Not really needed most of the time: Squeak existed
without closures for over 10 years. These are hard and expensive to
serialize.
c) "context free lambdas" a.k.a. "clean closures". State is stored in
objects. All state is passed to the block as arguments. These are easy
and cheap to serialize. A typical example for these is a sort block in a
SortedCollection.
The code you sent me uses b). It stores state in variables in the
context of the closure. But this is not really needed. I could convert
your code to c). See the attach. What I did is to take that state and
store it in an instance variable. There was yet another variable that
could simply be a temporal inside the block. Then, the default
implementation of Morph>>copy worked without problems.
I think it would be good to have different syntax for "clean" or
"context free" blocks. And encourage their use above real closures,
whenever possible.
Cheers,
Juan Vuletich
-------------- next part --------------
'From Cuis 4.2 of 25 July 2013 [latest update: #2322] on 14 May 2015 at 5:36:19.419438 pm'!
!classDefinition: #Animator category: #Animator!
Object subclass: #Animator
instanceVariableNames: 'actor action stepTime doneProc stepping'
classVariableNames: 'Animators'
poolDictionaries: ''
category: 'Animator'!
!Animator methodsFor: 'stepping' stamp: 'jmv 5/14/2015 17:31'!
stopStepping
"Stop getting sent the 'step' message."
| w |
w _ self runningWorld.
w ifNotNil: [w stopSteppingMorph: self].
stepping _ false! !
!Animator methodsFor: 'stepping' stamp: 'jmv 5/14/2015 17:32'!
startStepping
"Start stepping the receiver"
| w |
w _ self runningWorld.
w ifNotNil: [
w startStepping: self
at: Time localMillisecondClock
selector: #step
stepTime: self stepTime.
stepping _ true].
! !
!Animator methodsFor: 'stepping' stamp: 'jmv 5/14/2015 17:32'!
isStepping
stepping ifNil: [stepping _ false ].
^stepping ! !
!UserActionMorph class methodsFor: 'examples' stamp: 'jmv 5/14/2015 17:33'!
bouncingMorphExample
"Answer a UserActionMorph whose target moves,
bouncing off 'walls' of its container.
Start/stop when the mouse button is released (cheap click test)"
"
self bouncingMorphExample openInWorld.
"
| actionMorph |
actionMorph := UserActionMorph
icon: UserActionMorph bounceIcon
addProc: [ :userActionMorph :targetMorph | |bouncingAnimator|
bouncingAnimator := Animator
actor: targetMorph
action: (Animator simpleMoveBounceAction: 20 at 30)
stepTime: 60.
userActionMorph
addHandler: [ :ignore1 :ignore2 |
bouncingAnimator isStepping not
ifTrue: [ bouncingAnimator startStepping ]
ifFalse: [ bouncingAnimator stopStepping ]
]
propName: #'mouseButton1Up:localPosition:'
toMorph: targetMorph.
]
removeProc: [ :userActionMorph :targetMorph |
userActionMorph
removeHandlerProperty: #'mouseButton1Up:localPosition:'
fromMorph: targetMorph.
].
actionMorph name: 'MoveAndBounce'.
^ actionMorph
! !
!PalletLayoutMorph methodsFor: 'dropping/grabbing' stamp: 'jmv 5/14/2015 17:34'!
aboutToGrab: aMorph
"submorph is being grabbed by a hand.
Perform necessary adjustments (if any) and return the actual morph
that should be added to the hand.
Answer nil to reject the drag."
"^ aMorph shallowCopy postCopy "
"Nota Bene: clone to retain closures"
^aMorph copy! !
More information about the Cuis
mailing list