I just stumbled over the following behavior. To reproduce it, create a class with an inst var:
Object subclass: #Asdf
instanceVariableNames: 'countSeq'
classVariableNames: ''
poolDictionaries: ''
category: 'Asdf'
And a lazy-init getter:
countSeq
^countSeq ifNil: [
countSeq:=#(0) asOrderedCollection.
countSeq at: 1 put: (countSeq at: 1)+1.
countSeq
].
This works correctly. When I call Asdf new countSeq
then it returns an OrderedCollection(1)
every time.
However, if i remove the asOrderedCollection
:
countSeq
^countSeq ifNil: [
countSeq:=#(0).
countSeq at: 1 put: (countSeq at: 1)+1.
countSeq
].
And call Asdf new countSeq
multiple times, then i get #(1)
, #(2)
, #(3)
... .
How can this be explained?
(It looks to me like as if this array is behaving like a C static local variable. In fact, I tried it out: recompile the method and the unfortunate counter starts at 1 again)
This is because the literal array #(0)
is stored inside the method object.
Explained here: Why shouldn't I store into literal arrays in Smalltalk?