Search code examples
smalltalksqueak

Strange behavior in Squeak Smalltalk arrays


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)


Solution

  • 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?