2

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)

Bernd Elkemann
  • 23,242
  • 4
  • 37
  • 66

1 Answers1

3

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?

Tobias
  • 3,026
  • 20
  • 34
  • Yes, really a pitfall of the language. – Bernd Elkemann May 14 '16 at 11:22
  • 1
    Upvoted Tobias's answer on the page he ref's, I recommend everyone read it completely. – Bernd Elkemann May 14 '16 at 11:40
  • 1
    @BerndElkemann it is not a pitfall of the language, it's a consequence of having a system made of objects. The behavior becomes natural once our OO thinking overcomes our text-based reasoning. – Leandro Caniglia May 14 '16 at 15:50
  • Some dialects (visualworks) already forbid this. Modifying a literal is a bad thing and we might forbid that too in Squeak in near future (this will be possible with Spur VM). – aka.nice May 14 '16 at 17:54
  • @LeandroCaniglia There are two good choices in language design: either (1) literals should be immutable or (2) literals should be thought of as "producing objects" (not "being objects"). (The reason for the "literals being objects" in Smalltalk is historic, not good. For example I would never ask an array "in which method are you?") – Bernd Elkemann May 15 '16 at 07:25
  • @aka.nice Yes, blabla999 wrote this in his answer (on the linked question) – Bernd Elkemann May 15 '16 at 07:26
  • @BerndElkemann, I have always thought that "literals are objects" is a consequence of the general principle "everything is an object". In Smalltalk, we suffer for exceptions to that principle, not for honoring it. And we value simplicity for design decisions. – Carlos E. Ferro May 16 '16 at 19:41
  • @aka.nice as I said in my previous comment, for me "Modifying a literal is a bad thing" is like "evaluating 'true become: String new' is a bad thing". I would agree on tools not encouraging people to do that, but not on the VM forbidding me to do it – Carlos E. Ferro May 16 '16 at 19:44