stephane ducasse | 12 Oct 22:07
Favicon

About classVariables

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

Craig Latta | 13 Oct 05:19
Favicon

re: About classVariables


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)]

(Continue reading)

Martin Beck | 13 Oct 11:02
Favicon

Re: re: About classVariables

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

Paolo Bonzini | 13 Oct 11:30

Re: About classVariables

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

Craig Latta | 13 Oct 17:46
Favicon

re: About classVariables


      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)]
(Continue reading)

Paolo Bonzini | 13 Oct 18:47

Re: About classVariables

>      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

Craig Latta | 13 Oct 20:25
Favicon

re: About classVariables


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
(Continue reading)

Eliot Miranda | 13 Oct 21:43

Re: re: About classVariables



On Mon, Oct 13, 2008 at 2:02 AM, Martin Beck <martin.beck <at> 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.

nicolas cellier | 13 Oct 21:55

Re: About classVariables

Eliot Miranda a écrit :
> 
> 
> On Mon, Oct 13, 2008 at 2:02 AM, Martin Beck 
> <martin.beck <at> hpi.uni-potsdam.de <mailto:martin.beck <at> 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 | 13 Oct 22:29

Re: About classVariables

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...

Craig Latta | 13 Oct 22:20
Favicon

re: About classVariables


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)]

nicolas cellier | 13 Oct 22:42

Re: About classVariables

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...

Craig Latta | 13 Oct 23:09
Favicon

Re: About classVariables


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)]

nicolas cellier | 13 Oct 23:38

Re: About classVariables

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)]
> 
> 
> 

Craig Latta | 17 Oct 22:54
Favicon

re: About classVariables


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)]

Craig Latta | 13 Oct 23:00
Favicon

Re: About classVariables


      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)]

Eliot Miranda | 14 Oct 01:16

Re: re: About classVariables



On Mon, Oct 13, 2008 at 1:20 PM, Craig Latta <craig <at> 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)]




Craig Latta | 17 Oct 22:53
Favicon

Re: About classVariables


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)]

stephane ducasse | 14 Oct 14:42
Favicon

Re: re: About classVariables

> 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

Eliot Miranda | 13 Oct 21:44

Re: About classVariables



On Sun, Oct 12, 2008 at 1:11 PM, stephane ducasse <stephane.ducasse <at> free.fr> wrote:
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



stephane ducasse | 14 Oct 14:45
Favicon

Re: About classVariables

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.
>


Gmane