Smalltalk variables: why should I declare them?
Asked Answered
E

2

6

Basically I can use variables just by assigning something to them, for example:

x := something

It works fine.

But in classes, if I define a new method, but I don't declare the variable, I get an "assignment to undeclared variable x", so I have to use:

|x| x := something

Why is this?

Enneastyle answered 25/2, 2017 at 17:58 Comment(0)
V
12

As Uko mentions, there are different kinds of variables in Smalltalk and that's why we need to declare them differently. Let's review all of Smalltalk variables here for the sake of completeness.


Instance variables


Meaning: These are the ones that define the shape of the class. For example, the class Point defines the ivars x and y.

Declared: In the class definition.

Scope: Local, restricted to every instance.

Case: usually lowercase.


Class variables


Meaning: These variables are shared among several objects. They are not global though.

Declared: In the class definition.

Scope: Shared by the class, its metaclass, all subclasses, their metaclasses, all instances and all subinstances.

Case: usually Uppercase.


Class instance variables


Meaning: Are instance variables of the metaclass and therefore determine the shape of the class (not of its instances).

Declared: In the class definition.

Scope: Local, restricted to class-side methods.

Case: usually lowercase.


Temporaries


Meaning: These are auxiliary variables used in methods and blocks. They get allocated in the execution stack every time the method is activated (expect for those declared in a method or block closure and used in an inner block).

Declared: Between pipes as in | temp | at the beginning of the method's (or block) body.

Scope: Activation of the method or block.

Case: usually lowercase.


Pool variables


Meaning: Are held in global PoolDictionaries and can be used in any class that declares their use.

Declared: The class declares the usage of the PoolDictionary that defines them.

Scope: The class and all subclasses and metaclasses.

Case: usually Uppercase.


Global variables


Meaning: Are shared by every object in the system.

Declared: Nowhere. They are defined in the Smalltalk system dictionary by meas of Smalltalk at: <GlobalSymbol> put: <an object>. Once declared their value can be changed using :=.

Scope: The entire image.

Case: usually Uppercase.

Remark: Class names are global variables. However, you should not assign them using := (unless you know what you are doing.)


Pseudo variables


Meaning: They can be read but not written. These are: self, super, true, false and nil.

Declared: Nowhere.

Scope: Can be used everywhere. However, the meaning of self and supper changes with the object that uses them.


Method and Block Arguments


Meaning: They represent the formal arguments that the method or block will accept (and require) at every activation.

Declared: In the method signature or the beginning of the block.

Scope: The method or block that declares them.

Case: lowercase.


Workspace variables


Meaning: These are variables associated to workspaces (Playground in Pharo).

Declared: Usually not explicitly declared (the workspace will declare them behind the scenes).

Scope: The life of the workspace.

Case: lowercase.

Villalobos answered 25/2, 2017 at 19:23 Comment(6)
This is really great information for people starting out in Smalltalk. But... it doesn't actually answer the question (why declare?). If you were to ask a new question, something like "What types of variables are there in Smalltalk?" and move this answer there, I'd upvote both. ;-) Oh, and I would perhaps add that globals can be "defined" (well, added) by doing Smalltalk at: #GlobalName put: value. Come to think of it, this sort of thing would be even more appropriate in the Smalltalk documentation, which is still very sparse.Countrywoman
Hey, Leandro, thanks for writing this down, it is a very valuable information. Can I also copy this to StackOverflow Doc about Pharo?Barney
@AmosM.Carpenter Thanks for the hint. I've modified the text so now it includes the at:put: and the answer to the question. You are good to upvote now ;)Villalobos
@Barney Please, go ahead.Villalobos
I still would've preferred a separate question (because I think it might be more useful for someone googling about variables in Smalltalk), but here's your upvote. ;-) @Uko: kudos, I think the new documentation on SO could be a great place for helpful and general knowledge about Smalltalk!Countrywoman
The scope of workspace variable is limited to code snippets evaluated in the workspace/playground (the do it/print it/inspect it/debug it...). At best, this extend to the debugger when debugging the snippet, but that's not the case of all dialects, for example in Squeak <=5.3, the debugger has no idea how to resolve the workspace variables, so you can not evaluate arbitrary snippet from within the debugger, one must go back to the workspace, select variable and insect it from there.Cluff
B
7

x := something is allowed for scripting reasons. It, in fact, creates a variable x for your script. Now if you write x in a method without an explicit declaration, which kind of variable should be created? A temporary variable, or an instance variable, or a class variable, or a pool variable, or maybe a global binding? To avoid such issues you have to declare a variable somewhere and then use it.

There is another strategy used by different other languages, such as prefixing a variable with @@ if it has to be a class variable. But this introduces ugly syntax, limits your naming freedom, etc…

Barney answered 25/2, 2017 at 18:16 Comment(3)
In a language where everything is an object, you can also go a third route and have only one kind of variables: instance variables. Class variables are then just instance variables of the class object, temporary variables are instance variables of a lexical scope object, method parameter bindings are instance variables of a stack frame object, global variables are instance variables on a global environment object (or you just get rid of them, since they are evil anyway). Pools could be done with lexical nesting. I think that's what Self does. Newspeak does a similar thing except it doesn't …Exophthalmos
… have variables, it only has methods; variables are emulated using getter and setter methods for anonymous slots.Exophthalmos
@JörgWMittag, yes, you are right. In fact, in pharo we have Slots — objects representing instance variables. So maybe we can also move in the direction of turning other variables into slots. However, a developer still has to define which variable sits in which scope, which was the main topic of the questionBarney

© 2022 - 2024 — McMap. All rights reserved.