[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