hi all, expressions based on constants are remembered/cached for next evalations? If I compile:
Foo>>wakeUpTime ^ '6:30 am' asTime
I can see that bytecode still send #asTime to the string '6:30 am'. It means that each time the piece of code will be evaluated the string will be parsed too, even if it is clear that it will never produce a different object.
Same thing for CodeBlocks. In: [ :t | t < '06:30' asTime ] the right argument of #> will never change... and I feel I'll spend a lot of time on evaluating the same constant expressions during the execution of my program...
thanks Paolo
On Sun, 24 Nov 2013, paolo.bernardi.67@gmail.com wrote:
hi all, expressions based on constants are remembered/cached for next evalations?
No they are not.
If I compile:
Foo>>wakeUpTime ^ '6:30 am' asTime
I can see that bytecode still send #asTime to the string '6:30 am'. It means that each time the piece of code will be evaluated the string will be parsed too, even if it is clear that it will never produce a different object.
It's not constant at all. There are multiple ways to change the return value of that method. The easiest one is to change the implementation of String >> #asTime, or any method that is sent by that method, etc.
Same thing for CodeBlocks. In: [ :t | t < '06:30' asTime ] the right argument of #> will never change... and I feel I'll spend a lot of time on evaluating the same constant expressions during the execution of my program...
Since message sends are late bound, it means that if you want to cache something, then you have to do it yourself. There are various ways to cache something. In your case if you know that you always want '6:30 am', then you can use a class variable to store it:
Foo class >> #initialize
WakeUpTime := '6:30 am' asTime
and then
Foo >> #wakeUpTime
^WakeUpTime
This technique has some drawbacks, notably that you'll have to evaluate the class side #initialize when you're writing the code. A common solution for this is to use lazy initalization instead:
Foo class >> #wakeUpTime
^WakeUpTime ifNil: [ WakeUpTime := '6:30 am' ]
and then
Foo >> #wakeUpTime
^self class wakeUpTime
You shouldn't use the class variable directly from the instance side in this case, otherwise you can't guarantee that it's initialized. If your class won't have subclasses, then you can use a class instance variable instead of a class variable, because it is not accessible directly from the instance side.
And there's also a hack, which caches the value in the method. I don't suggest you to use this techique, but it can be useful sometimes:
Foo >> #wakeUpTime
| cache | cache := #(nil). ^(cache at: 1) ifNil: [ cache at: 1 put: '6:30 am' asTime ]
Levente
thanks Paolo _______________________________________________ Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
beginners@lists.squeakfoundation.org