Counter question: what do you need that list for, meaning, what do you intend to do with the items?
For mere technical purposes, checking only for Global seems like the "right" way to me since the system takes care to choose the correct binding class (i.e., Global or ClassBinding) automatically. Eliot's variant is more precautious, but it should only catch cases were something went wrong in the first place, if I am not mistaken. For practical purposes, selecting with #isBehavior and/or #canAssign as indicated by Bert might be the better choice. You could even end up doing this: Smalltalk globals associationsDo: [:each | (each value isBehavior not or: [each canAssign]) ifTrue: [...]].
By the way, regarding the automatic choice of the binding class, I just noted this:
MyGlobal := Object. "when prompted, choose 'declare global' for the parser" (Smalltalk globals associationAt: #MyGlobal) class ==> Global
Smalltalk globals at: #MyGlobal2 put: Object. (Smalltalk globals associationAt: #MyGlobal2) class ==> ClassBinding "this would contradict Eliot's previous assumption: 'But my point is that the classes in global are in bindings whose keys are == to their name. Everything else is a global variable.'" "also note that this is not the same thing as proper aliasing, because Alias/asBinding: is not involved"
Smalltalk globals at: #MyGlobal2 put: nil. "equivalent to 'declare global'" MyGlobal2 := Object. "which should mean (Smalltalk globals bindingOf: #MyGlobal2) value: Object." (Smalltalk globals associationAt: #MyGlobal2) class ==> Global
So when you want a Global that is referring to a class, you currently must not use Environment>>at:put:/bind:to: right away.
Kind regards, Jakob
2017-12-30 15:33 GMT+01:00 H. Hirzel hannes.hirzel@gmail.com:
P.S. In a Squeak 6.0a image both expressions give an array with 18 objects of class 'Global'
Binding subclass: #Global instanceVariableNames: 'value' classVariableNames: '' poolDictionaries: '' category: 'Environments-Core'
On 12/30/17, H. Hirzel hannes.hirzel@gmail.com wrote:
An attempt to summarize this thread:
To create a list of globals Levente proposes
Array streamContents: [ :stream | Smalltalk globals associationsDo: [ :binding | binding class == Global ifTrue: [ stream nextPut: binding ] ] ].
Wheras Eliot has:
Array streamContents: [ :stream | Smalltalk globals associationsDo: [ :binding | (binding class == Global and: [ (binding value isBehavior and: [ binding key == binding value name ] ) not ] ) ifTrue: [ stream nextPut: binding ] ] ].
The question is what should be in the 'List of globals'?
a) 'bindings' which are an instance of Global (Levente) b) 'bindings' which are an instance of Global and in addition do not point to a class. (Eliot)
--Hannes
On 4/5/17, Bert Freudenberg bert@freudenbergs.de wrote:
On Tue 4. Apr 2017 at 19:05, Levente Uzonyi leves@caesar.elte.hu wrote:
On Tue, 4 Apr 2017, Eliot Miranda wrote:
On Apr 4, 2017, at 7:02 AM, Bert Freudenberg bert@freudenbergs.de
wrote:
On Tue, Apr 4, 2017 at 3:47 PM, Eliot Miranda <
eliot.miranda@gmail.com> wrote:
Hi Levente, > On Apr 3, 2017, at 11:14 AM, Levente Uzonyi <
leves@caesar.elte.hu> wrote:
> > The correct solution is: > > Array streamContents: [ :stream | > Smalltalk globals associationsDo: [ :binding | > binding class == Global ifTrue: [ stream nextPut:
binding ] ] ].
Or shorter
Smalltalk globals declarations select: #canAssign
maybe? Unlike class bindings, global vars are writable.
I don't like this. I see writability as orthogonal. I'm sure there's
good uses for read-only globals that are not classes. I like the tenseness though. So
Smalltalk globals declarations reject: #isClassBinding
with isClassBinding ^value isBehavior and: [key == value name]
Why not just ^true? It's a ClassBinding even if it's not initialized properly. And that should be the Environment's responibility.
Why not Array streamContents: [ :stream | Smalltalk globals associationsDo: [ :binding | (binding class == Global and: [ binding value isBehavior and: [ binding key == binding value name ] ]) ifTrue: [ stream nextPut: binding ] ] ].
Because we want to know the global *variables*, that is everything *but*
the class bindings. So we look for instances of Global, not ClassBinding, no matter the value.
Forgive me; I missed a not in there. But my point is that the classes
in global are in bindings whose keys are == to their name. Everything else is a global variable.
We have separate subclasses: ClassBinding and Global. We should use those.
Levente
Yep. Besides, with renaming on import the name of the class is not necessarily the same as its binding key.
- Bert -
> The role of declarations and bindings is still not clear in
Environments, therefore, as I wrote it before, unrelated to tool support, I still consider Environments to be incomplete.
I thought 'declarations' are the things owned by this environment
(excluding imports), whereas 'bindings' are the things visible in this environment (including imports).
Is there a definition in text somewhere? Colin?
- Bert -