Hi
to my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that?
For me this is a conceptual bug.
Stef
Hi Stef--
To my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that? For me this is a conceptual bug.
Actually, metaclasses don't really have class variables at all. Class variables are defined by Class, which is a sibling of Metaclass, not a superclass. There's a method in Behavior which just answers a new empty Set for classVarNames; this is what you're invoking when you evaluate [TheRoot class classVarNames].
I guess that's in there so that "explain" and "browse class var refs" behave as someone in the past wanted them to. Do you have a need which conflicts with this? Do you actually need to use TheRoot's class variables in code where (TheRoot class) is the receiver?
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
Craig Latta wrote:
Hi Stef--
To my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that? For me this is a conceptual bug.
Actually, metaclasses don't really have class variables at all.
Class variables are defined by Class, which is a sibling of Metaclass, not a superclass. There's a method in Behavior which just answers a new empty Set for classVarNames; this is what you're invoking when you evaluate [TheRoot class classVarNames].
However,
TheRoot classPool = TheRoot class classPool
evaluates to true...
Regards, Martin
Martin Beck wrote:
Craig Latta wrote:
Hi Stef--
To my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that? For me this is a conceptual bug.
TheRoot classPool = TheRoot class classPool
evaluates to true...
Indeed, I would have expected classVarNames to be just "self classPool keys" or "self classPool keys inject: '' into: ' [:a :b | a,b,' ']".
Paolo
Martin Beck writes:
TheRoot classPool = TheRoot class classPool
evaluates to true...
I'd say that's a bug (as is Behavior>>classVarNames answering an empty Set), because the class variables for (TheRoot class) should be those defined by Metaclass, if we're going to be consistent (the behavior of the system would end up being the same, since the class pool for Metaclass is empty). I also notice that Metaclass>>classPool was added after Squeak 3.2.
Paolo Bonzini writes:
Indeed, I would have expected classVarNames to be just "self classPool keys" or "self classPool keys inject: '' into: ' [:a :b | a,b,' ']".
For the reason above, I'd say that's wrong also.
But again, I'm wondering what real difficulty is caused by this.
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
I'd say that's a bug (as is Behavior>>classVarNames answering an
empty Set),
Why? (#allClassVarNames is a different story).
because the class variables for (TheRoot class) should be those defined by Metaclass, if we're going to be consistent (the behavior of the system would end up being the same, since the class pool for Metaclass is empty). I also notice that Metaclass>>classPool was added after Squeak 3.2.
Not really, class variables are explicitly defined to apply both on the instance and on the class side. So the class pool should be the same, without any #theClass.
Paolo
Hi Paolo--
I'd say that's a bug (as is Behavior>>classVarNames answering an empty Set),
Why? (#allClassVarNames is a different story).
because the class variables for (TheRoot class) should be those defined by Metaclass, if we're going to be consistent...
You just quoted my answer, so I don't see why you're asking again.
...class variables are explicitly defined to apply both on the instance and on the class side. So the class pool should be the same, without any #theClass.
The class pool for an instance of Metaclass should be the class pool defined by Metaclass. So, for example, the class pool for (Array class) should be the class pool defined by Metaclass. This is different than the class pool for Array or an instance of Array, which is the class pool defined by Array.
Again, until someone cites a reason why this is of practical significance, I don't think it's a very interesting issue.
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
On Mon, Oct 13, 2008 at 2:02 AM, Martin Beck <martin.beck@hpi.uni-potsdam.de
wrote:
Craig Latta wrote:
Hi Stef--
To my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that? For me this is a conceptual bug.
Actually, metaclasses don't really have class variables at all.
Class variables are defined by Class, which is a sibling of Metaclass, not a superclass. There's a method in Behavior which just answers a new empty Set for classVarNames; this is what you're invoking when you evaluate [TheRoot class classVarNames].
However,
TheRoot classPool = TheRoot class classPool
evaluates to true...
Regards, Martin
One fix is to add the following method: ------------8<----------- !Metaclass methodsFor: 'class variables' stamp: 'eem 10/13/2008 12:37'! classVarNames "Answer a Set of the names of the class variables defined in the receiver's instance."
^thisClass classVarNames! ! ------------8<----------- c.f. Metaclass>>classPool.
But a better fix is to move Class>>classVarNames to ClassDescription: ------------8<----------- 'From Croquet1.0beta of 11 April 2006 [latest update: #1] on 13 October 2008 at 12:41:36 pm'!
!ClassDescription methodsFor: 'class variables' stamp: 'eem 10/13/2008 12:41'! classVarNames "Answer a Set of the names of the class variables defined in the receiver."
^self classPool keys! !
Class removeSelector: #classVarNames! ------------8<-----------
Whoever said that the class variables of a metaclass should be those of Metaclass is very wrong. Code compiled in the context of a metaclass includes the class variables of the non-metaclass (metaclass's instance), otherwise one couldn't access class variables in class-side methods.
Eliot Miranda a écrit :
On Mon, Oct 13, 2008 at 2:02 AM, Martin Beck <martin.beck@hpi.uni-potsdam.de mailto:martin.beck@hpi.uni-potsdam.de> wrote:
Craig Latta wrote: > > Hi Stef-- > >> To my stupefaction I discovered that the classVariables of a class are >> not the same as the ones of its metaclass. >> >> TheRoot classVarNames ~= TheRoot class classVarNames >> >> Does any body have some ideas why this is like that? For me this is a >> conceptual bug. > > Actually, metaclasses don't really have class variables at all. > Class variables are defined by Class, which is a sibling of Metaclass, > not a superclass. There's a method in Behavior which just answers a new > empty Set for classVarNames; this is what you're invoking when you > evaluate [TheRoot class classVarNames]. > However, TheRoot classPool = TheRoot class classPool evaluates to true... Regards, Martin
One fix is to add the following method: ------------8<----------- !Metaclass methodsFor: 'class variables' stamp: 'eem 10/13/2008 12:37'! classVarNames "Answer a Set of the names of the class variables defined in the receiver's instance."
^thisClass classVarNames! ! ------------8<----------- c.f. Metaclass>>classPool.
But a better fix is to move Class>>classVarNames to ClassDescription: ------------8<----------- 'From Croquet1.0beta of 11 April 2006 [latest update: #1] on 13 October 2008 at 12:41:36 pm'!
!ClassDescription methodsFor: 'class variables' stamp: 'eem 10/13/2008 12:41'! classVarNames "Answer a Set of the names of the class variables defined in the receiver."
^self classPool keys! !
Class removeSelector: #classVarNames! ------------8<-----------
Whoever said that the class variables of a metaclass should be those of Metaclass is very wrong. Code compiled in the context of a metaclass includes the class variables of the non-metaclass (metaclass's instance), otherwise one couldn't access class variables in class-side methods.
It is funny with Object because:
(Object class allSuperclasses includes: Object).
So the Object classPool keys will be accessible twice (It does not seem to hurt).
Nicolas
nicolas cellier a écrit :
It is funny with Object because:
(Object class allSuperclasses includes: Object).
So the Object classPool keys will be accessible twice (It does not seem to hurt).
Nicolas
Nah, forget it, it does not work that way...
UndefinedObject class>>someSuperObsolete ^ObsoleteSubclasses
would not reach this class var definition though:
(Behavior classVarNames includes: #ObsoleteSubclasses and: [ UndefinedObject class allSuperclasses includes: Behavior].
Which is confirmed by:
UndefinedObject class allClassVarNames includes: #ObsoleteSubclasses.
There is definitely some trick here...
Hi Eliot--
Whoever said that the class variables of a metaclass should be those of Metaclass is very wrong. Code compiled in the context of a metaclass includes the class variables of the non-metaclass (metaclass's instance), otherwise one couldn't access class variables in class-side methods.
I think you're confusing metalevels. If I compile a class-side method for Array, and I use a class variable, conceptually it's one of Array's class variables I'm using, yes? What the class variables of (Array class) might be is irrelevant. Yes, during compilation, Metaclass>>scopeHas:ifTrue: delegates to the receiver's sole instance, but that doesn't mean that a metaclass has the same class variables as its sole instance.
To say otherwise is to introduce a conceptual inconsistency into the system: the class variables of an object are defined by its class, except if that object is a metaclass. Further, suppose the class variables pool for Metaclass were not empty. By your logic instances of Metaclass don't have access to it.
I guess we disagree here.
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
Craig Latta a écrit :
Hi Eliot--
Whoever said that the class variables of a metaclass should be those of Metaclass is very wrong. Code compiled in the context of a metaclass includes the class variables of the non-metaclass (metaclass's instance), otherwise one couldn't access class variables in class-side methods.
I think you're confusing metalevels. If I compile a class-side
method for Array, and I use a class variable, conceptually it's one of Array's class variables I'm using, yes? What the class variables of (Array class) might be is irrelevant. Yes, during compilation, Metaclass>>scopeHas:ifTrue: delegates to the receiver's sole instance, but that doesn't mean that a metaclass has the same class variables as its sole instance.
To say otherwise is to introduce a conceptual inconsistency into
the system: the class variables of an object are defined by its class, except if that object is a metaclass. Further, suppose the class variables pool for Metaclass were not empty. By your logic instances of Metaclass don't have access to it.
I guess we disagree here.
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
That's how it works indeed, but the example I provided sounds then like very misleading (a bug?):
UndefinedObject class allClassVarNames includes: #ObsoleteSubclasses.
which is a class var of Behavior...
Hi Nicolas--
That's how it works indeed, but the example I provided sounds then like very misleading (a bug?):
UndefinedObject class allClassVarNames includes: #ObsoleteSubclasses.
which is a class var of Behavior...
(UndefinedObject class) is an instance of Metaclass, and Metaclass is a subclass of Behavior, so I would expect Behavior's class variable names to show up in a list of all the class variables names for (UndefinedObject class).
I swear I'm getting real work done. ;)
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
Craig Latta a écrit :
Hi Nicolas--
That's how it works indeed, but the example I provided sounds then like very misleading (a bug?):
UndefinedObject class allClassVarNames includes: #ObsoleteSubclasses.
which is a class var of Behavior...
(UndefinedObject class) is an instance of Metaclass, and Metaclass
is a subclass of Behavior, so I would expect Behavior's class variable names to show up in a list of all the class variables names for (UndefinedObject class).
Well not exactly... I make a parallel reasonning:
nil is an instance of UndefinedObject, UndefinedObject is a subclass of Object, so I expect Object's class variable names to show up in a list of all the class variables names for nil
nil doesNotUnderstand: #allClassVarNames
It runs through (UndefinedObject class superclasses) rather than (UndefinedObject class class).
UndefinedObject class < Object class < ProtoObject class < Class < ClassDescription < Behavior
I swear I'm getting real work done. ;)
Oh yes, this thread is really bound to be unproductive. You do not need to answer this!
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
Hi Nicolas--
...the example I provided sounds very misleading (a bug?):
UndefinedObject class allClassVarNames includes: #ObsoleteSubclasses.
which is a class var of Behavior...
(UndefinedObject class) is an instance of Metaclass, and Metaclass is a subclass of Behavior, so I would expect Behavior's class variable names to show up in a list of all the class variables names for (UndefinedObject class).
Well not exactly... I make a parallel reasoning:
nil is...
Oh, I didn't realize you were really interested in the class variables of nil. :) I'd expect the class variables of nil to be those of UndeclaredObject, not of (UndeclaredObject class).
I swear I'm getting real work done. ;)
Oh yes, this thread is really bound to be unproductive. You do not need to answer this!
Heh. To atone for it, I wrote a separate message about the design of Naiad, Spoon's module sysem. :)
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
A couple of elaborations...
If I compile a class-side method for Array, and I use a class variable, conceptually it's one of Array's class variables I'm using, yes? What the class variables of (Array class) might be is irrelevant. Yes, during compilation, Metaclass>>scopeHas:ifTrue: delegates to the receiver's sole instance, but that doesn't mean that a metaclass has the same class variables as its sole instance.
In particular, in Metaclass>>scopeHas:ifTrue: we're referring to the scope defined by the receiver of the method we're compiling (Array), not the object being asked this scope question (Array class). There's probably a better name than "scopeHas:".
To say otherwise is to introduce a conceptual inconsistency into the system: the class variables of an object are defined by its class, except if that object is a metaclass. Further, suppose the class variables pool for Metaclass were not empty. By your logic instances of Metaclass don't have access to it.
That is, having put an entry into the class variables pool for Metaclass, if I then ask (Array class) for its class variable names, I won't get the new class variable name in my answer if it just delegates to its sole instance.
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
On Mon, Oct 13, 2008 at 1:20 PM, Craig Latta craig@netjam.org wrote:
Hi Eliot--
Whoever said that the class variables of a metaclass should be those of Metaclass is very wrong. Code compiled in the context of a metaclass includes the class variables of the non-metaclass (metaclass's instance), otherwise one couldn't access class variables in class-side methods.
I think you're confusing metalevels. If I compile a class-side method
for Array, and I use a class variable, conceptually it's one of Array's class variables I'm using, yes? What the class variables of (Array class) might be is irrelevant. Yes, during compilation, Metaclass>>scopeHas:ifTrue: delegates to the receiver's sole instance, but that doesn't mean that a metaclass has the same class variables as its sole instance.
When compiling code in Foo class, as opposed to Foo, the compiler asks Foo class to lookup variables, not Foo. Hence if the code refers to a class inst var of Foo it will be in scope because this class inst var will be one of Foo class's inst vars. Similarly, when the compiler asks Foo class to bind a variable that is actually a class variable of Foo, it is up to Foo class to look in Foo's class pool, not the compiler.
So it makes sense to me that Foo class's class pool is the same as Foo's.
To say otherwise is to introduce a conceptual inconsistency into the
system: the class variables of an object are defined by its class, except if that object is a metaclass. Further, suppose the class variables pool for Metaclass were not empty. By your logic instances of Metaclass don't have access to it.
The only place that instances of Metaclass have access to Metaclass's class pool is in methods on Metaclass. Class-side methods in metaclasses other than Metaclass class do _not_ have access to Metaclass class variables. Try it :)
I guess we disagree here.
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
Hi Eliot--
When compiling code in Foo class, as opposed to Foo, the compiler asks Foo class to lookup variables, not Foo.
I didn't say it would (although when looking for Foo's class variables, (Foo class) will delegate to Foo).
Hence if the code refers to a class inst var of Foo it will be in scope because this class inst var will be one of Foo class's inst vars.
No, it's in scope because it's a class inst var of *Foo*, like you said in the first part of your sentence. :) In particular, the class instance variable will have been put in the encoder's scopeTable by an earlier invocation of Encoder>>init:context:notifying:.
Similarly, when the compiler asks Foo class to bind a variable that is actually a class variable of Foo, it is up to Foo class to look in Foo's class pool, not the compiler.
You're referring to Metaclass>>scopeHas:ifTrue:, which does indeed delegate to the receiver's sole instance. But in that method "scope" refers to the scope associated with the intended receiver of the method we're compiling (Foo), not the object being asked this scope question (Foo class). This doesn't say anything about what the class variables of (Foo class) are, only that (Foo class) is responsible for answering the class variables of Foo when compiling methods to be run with Foo as receiver.
To say otherwise is to introduce a conceptual inconsistency into the system: the class variables of an object are defined by its class, except if that object is a metaclass. Further, suppose the class variables pool for Metaclass were not empty. By your logic instances of Metaclass don't have access to it.
The only place that instances of Metaclass have access to Metaclass's class pool is in methods on Metaclass.
As I clarified in a followup message, I was referring to what a metaclass should answer as its class variables, not how to bind anything during compilation of methods for which that metaclass will be the receiver (those would just be instance-side methods of Metaclass, as you say). For example, having put an entry into the class variables pool for Metaclass, if I then ask (Array class) for all its class variable names, I won't get the new class variable name in my answer by your logic.
Class-side methods in metaclasses other than Metaclass class do _not_ have access to Metaclass class variables. Try it :)
Eh? I never said that any of those methods should be able to bind class variable names from Metaclass. I was talking about what one should get when asking a metaclass point-blank for all its class variable names (something that never happens as far as I can remember, hence the exquisite angels-on-the-head-of-a-pin nature of this conversation :).
-C
-- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)]
One fix is to add the following method: ------------8<----------- !Metaclass methodsFor: 'class variables' stamp: 'eem 10/13/2008 12:37'! classVarNames "Answer a Set of the names of the class variables defined in the receiver's instance."
^thisClass classVarNames! ! ------------8<----------- c.f. Metaclass>>classPool.
But a better fix is to move Class>>classVarNames to ClassDescription: ------------8<----------- 'From Croquet1.0beta of 11 April 2006 [latest update: #1] on 13 October 2008 at 12:41:36 pm'!
!ClassDescription methodsFor: 'class variables' stamp: 'eem 10/13/2008 12:41'! classVarNames "Answer a Set of the names of the class variables defined in the receiver."
^self classPool keys! !
Class removeSelector: #classVarNames! ------------8<-----------
Whoever said that the class variables of a metaclass should be those of Metaclass is very wrong. Code compiled in the context of a metaclass includes the class variables of the non-metaclass (metaclass's instance), otherwise one couldn't access class variables in class-side methods.
Tx
Stef
On Sun, Oct 12, 2008 at 1:11 PM, stephane ducasse stephane.ducasse@free.frwrote:
Hi
to my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that?
For me this is a conceptual bug.
Its just a vanilla bug because Class>>classVarNames is defined in the wrong place. It should be defined in ClassDescription. See my previous message.
Stef
Yeap. I was shocked :) this is good to know that this was already fixed in Croquet. Stef
Hi
to my stupefaction I discovered that the classVariables of a class are not the same as the ones of its metaclass.
TheRoot classVarNames ~= TheRoot class classVarNames
Does any body have some ideas why this is like that?
For me this is a conceptual bug.
Its just a vanilla bug because Class>>classVarNames is defined in the wrong place. It should be defined in ClassDescription. See my previous message.
squeak-dev@lists.squeakfoundation.org