How does Pharo store instance variables?
I am trying to study Pharo's internals and I am now curious how it stores class variables. I notice that in order to have a class `Greeter` with a "static" variable `greeting`, I need to make `greeting` an instance variable under "show show the class side" and create a "Getter" and "Setter" for this "instance variable". First thing that confuses me is, why is this called an instance variable if this particular "static" method is not bound to any particular instance? Is it just because it is defined in an "instance" of a "ProtoClass"? Second thing that confuses me is, where are these pairs of ("instance variable name" => "instance variable value") stored? I know that I can call Transcript show: ((Greeter class) instanceVariables at: 1). which prints "greeting". and Transcript show: Greeter instanceVariables class. which prints "Array"(curious, i expected a Dictionary mapping Strings to Object). Transcript show: ((Greeter class) instanceVariables at: 1) class. prints "ByteSymbol". Now I am confused, where are the actual values of the "static variables" stored? I can find the names, but can't understand where the values are hidden. Can somebody help me understand this? -- View this message in context: http://forum.world.st/How-does-Pharo-store-instance-variables-tp4917924.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
If you defined the variable as an instance variable in the class side, you can access it as Greeter instVarNamed: 'greeting' or Greeter instVarAt: 1 But also you can define class variables from the instance side, which is slightly different (and I think most common, isn't it?) Object subclass: #Greeter instanceVariableNames: '' classVariableNames: 'greeting' package: 'Greetings' if that is the case, there is in fact a dictionary which is accessed by doing Greeting classPool On Mon, Oct 3, 2016 at 10:23 PM, CodeDmitry <dimamakhnin@gmail.com> wrote:
I am trying to study Pharo's internals and I am now curious how it stores class variables.
I notice that in order to have a class `Greeter` with a "static" variable `greeting`, I need to make `greeting` an instance variable under "show show the class side" and create a "Getter" and "Setter" for this "instance variable".
First thing that confuses me is, why is this called an instance variable if this particular "static" method is not bound to any particular instance? Is it just because it is defined in an "instance" of a "ProtoClass"?
Second thing that confuses me is, where are these pairs of ("instance variable name" => "instance variable value") stored? I know that I can call
Transcript show: ((Greeter class) instanceVariables at: 1).
which prints "greeting".
and
Transcript show: Greeter instanceVariables class.
which prints "Array"(curious, i expected a Dictionary mapping Strings to Object).
Transcript show: ((Greeter class) instanceVariables at: 1) class.
prints "ByteSymbol".
Now I am confused, where are the actual values of the "static variables" stored? I can find the names, but can't understand where the values are hidden.
Can somebody help me understand this?
-- View this message in context: http://forum.world.st/How- does-Pharo-store-instance-variables-tp4917924.html Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
Oh! I see where I got confused now! "static" variables in Pharo outlive their Playground call! If I call Greeter greet. Greeter greeting: 'Hi!'. Greeter greet. Even if greet sets greeting to an initial value if it is nil, it will forever then stay 'Hi!' until I change it or reset it. So it is not unreasonable to get a response 'Hi! Hi!' in the playground even though 'Hi!' only gets set after greet is called, since the global state outlives the Transcript! -- View this message in context: http://forum.world.st/How-does-Pharo-store-instance-variables-tp4917924p4917... Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
On Tue, Oct 4, 2016 at 9:37 AM, CodeDmitry <dimamakhnin@gmail.com> wrote:
Oh! I see where I got confused now!
"static" variables in Pharo outlive their Playground call!
More than that. They outlive closing the image. The paradigm*** shift you need to make is that while the lifetime of "static" variables of a C/C++ program ends when program execution ends, and even though you stop and start execution of the VM, the execution of the "Image" *never* ends, it is only suspended. Try this experiment... In the System Browser... Morph subclass: #MyMorph instanceVariableNames: '' classVariableNames: '' package: 'AnExperiment' MyMorph>>step self right > Display width ifTrue: [ self left: 0 ]. self left: self left + 10. MyMorph>>stepTime ^100 In Playground... (m := MyMorph new) openInWorld. "After it has been running a while, Save & Quit the image**, then restart it. Notice the movement of the morph continues from where it left off." m delete. "...sometime later" **Even copy the image and changes to another machine they start it up there. *** and perhaps you might notice a change in your perception of "what is possible" from exposure in your course to the "dead" language of Smalltalk. And further, consider MyMorph is part of a control system for a nuclear power plant or financial trading system operating 365x24 and you want to change MyMorph from moving right to moving left. Consider how you would do that in C++ without stopping the system for even a second, compared to doing that in Pharo. Now Pharo may not be production ready (i.e. $$$) to run a nuclear power plant, but the concept of making such "live" changes to compiled code is now a concept you can carry forward to other disciplines. cheers -ben
If I call
Greeter greet. Greeter greeting: 'Hi!'. Greeter greet.
Even if greet sets greeting to an initial value if it is nil, it will forever then stay 'Hi!' until I change it or reset it.
So it is not unreasonable to get a response 'Hi! Hi!' in the playground even though 'Hi!' only gets set after greet is called, since the global state outlives the Transcript!
Hi guys, I think such discussions should be done in pharo-users. These discussions will be very interesting to follow by users/beginners. Pharo-dev is more about contributions/discussions aboit core development of Pharo. Thank you Envoyé de mon iPhone
Le 4 oct. 2016 à 05:00, Ben Coman <btc@openinworld.com> a écrit :
On Tue, Oct 4, 2016 at 9:37 AM, CodeDmitry <dimamakhnin@gmail.com> wrote: Oh! I see where I got confused now!
"static" variables in Pharo outlive their Playground call!
More than that. They outlive closing the image. The paradigm*** shift you need to make is that while the lifetime of "static" variables of a C/C++ program ends when program execution ends, and even though you stop and start execution of the VM, the execution of the "Image" *never* ends, it is only suspended.
Try this experiment...
In the System Browser... Morph subclass: #MyMorph instanceVariableNames: '' classVariableNames: '' package: 'AnExperiment'
MyMorph>>step self right > Display width ifTrue: [ self left: 0 ]. self left: self left + 10.
MyMorph>>stepTime ^100
In Playground... (m := MyMorph new) openInWorld. "After it has been running a while, Save & Quit the image**, then restart it. Notice the movement of the morph continues from where it left off." m delete. "...sometime later"
**Even copy the image and changes to another machine they start it up there.
*** and perhaps you might notice a change in your perception of "what is possible" from exposure in your course to the "dead" language of Smalltalk. And further, consider MyMorph is part of a control system for a nuclear power plant or financial trading system operating 365x24 and you want to change MyMorph from moving right to moving left. Consider how you would do that in C++ without stopping the system for even a second, compared to doing that in Pharo. Now Pharo may not be production ready (i.e. $$$) to run a nuclear power plant, but the concept of making such "live" changes to compiled code is now a concept you can carry forward to other disciplines.
cheers -ben
If I call
Greeter greet. Greeter greeting: 'Hi!'. Greeter greet.
Even if greet sets greeting to an initial value if it is nil, it will forever then stay 'Hi!' until I change it or reset it.
So it is not unreasonable to get a response 'Hi! Hi!' in the playground even though 'Hi!' only gets set after greet is called, since the global state outlives the Transcript!
On 04/10/16 03:37, CodeDmitry wrote:
"static" variables in Pharo outlive their Playground call!
There is no such thing as a "static" method or "static" variable in Smalltalk. At least not in the Java sense. In most languages a static method is simply a function attached to a class (because there is no other place to put it). But it does not imply any meaning to this/self. It's similar for variables ... because Global Variables are frowned upon most programmers simply attach them to a class - making them "static". That's different in Smalltalk. In Smalltalk /every method is an instance method/! "Regular methods" are defined by the instance's class and executed within an instance context. "Class methods" are defined by the instances's *meta*class and also executed in an instance context - only that the instance at that point is the class itself! Because there is a 1:1 relationship between the class (defining the instance behavior) and it's meta-class (defining the class behavior) the Smalltalk Browser provides a unified view. E.g. if you create a class in the class browser you'll also create it's metaclass. The code you see when browsing "the instance side" is the method dictionary of the class. If you switch to "the class side" in the class browser you are essentially browsing the method dictionary of it's metaclass! It's a bit more complex for variables. Ignoring regular instance variables a "class variable" is defined by a class and is shared with all it's subclasses. E.g. a class hierarchy, where only one of the subclasses is used for a Singleton at a time could use a class variable "Current". A "class instance variable" on the other hand does not share it's value with subclasses. E.g. the class name and it's method dictionary could be candidates for class inctance variables - i.e. they are unique per class - not per hierarchy! IMHO this implementation of instances/classes/metaclasses is very different from the "static" stuff used today. Take a look here (especially Chapter 5 in the Blue Book) for more details: http://esug.org/data/Articles/Columns/EwingPapers/cvars&cinst_vars.pdf http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook.pdf CU, Udo
"static" the worst name for a class variable. On Tue, 4 Oct 2016 at 09:26, Udo Schneider <udo.schneider@homeaddress.de> wrote: On 04/10/16 03:37, CodeDmitry wrote:
"static" variables in Pharo outlive their Playground call!
There is no such thing as a "static" method or "static" variable in Smalltalk. At least not in the Java sense. In most languages a static method is simply a function attached to a class (because there is no other place to put it). But it does not imply any meaning to this/self. It's similar for variables ... because Global Variables are frowned upon most programmers simply attach them to a class - making them "static". That's different in Smalltalk. In Smalltalk /every method is an instance method/! "Regular methods" are defined by the instance's class and executed within an instance context. "Class methods" are defined by the instances's *meta*class and also executed in an instance context - only that the instance at that point is the class itself! Because there is a 1:1 relationship between the class (defining the instance behavior) and it's meta-class (defining the class behavior) the Smalltalk Browser provides a unified view. E.g. if you create a class in the class browser you'll also create it's metaclass. The code you see when browsing "the instance side" is the method dictionary of the class. If you switch to "the class side" in the class browser you are essentially browsing the method dictionary of it's metaclass! It's a bit more complex for variables. Ignoring regular instance variables a "class variable" is defined by a class and is shared with all it's subclasses. E.g. a class hierarchy, where only one of the subclasses is used for a Singleton at a time could use a class variable "Current". A "class instance variable" on the other hand does not share it's value with subclasses. E.g. the class name and it's method dictionary could be candidates for class inctance variables - i.e. they are unique per class - not per hierarchy! IMHO this implementation of instances/classes/metaclasses is very different from the "static" stuff used today. Take a look here (especially Chapter 5 in the Blue Book) for more details: http://esug.org/data/Articles/Columns/EwingPapers/cvars&cinst_vars.pdf http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook.pdf CU, Udo
Wait im confused, did moving my thread while you guys were writing response to Users forum make the thread retained in this forum as well? O.o -- View this message in context: http://forum.world.st/Re-How-does-Pharo-store-instance-variables-tp4917950p4... Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
On 10/03/2016 01:23 PM, CodeDmitry wrote:
I am trying to study Pharo's internals and I am now curious how it stores class variables.
I notice that in order to have a class `Greeter` with a "static" variable `greeting`, I need to make `greeting` an instance variable under "show show the class side" and create a "Getter" and "Setter" for this "instance variable".
First thing that confuses me is, why is this called an instance variable if this particular "static" method is not bound to any particular instance? Is it just because it is defined in an "instance" of a "ProtoClass"?
Second thing that confuses me is, where are these pairs of ("instance variable name" => "instance variable value") stored? I know that I can call
Transcript show: ((Greeter class) instanceVariables at: 1).
which prints "greeting".
and
Transcript show: Greeter instanceVariables class.
which prints "Array"(curious, i expected a Dictionary mapping Strings to Object).
Transcript show: ((Greeter class) instanceVariables at: 1) class.
prints "ByteSymbol".
Now I am confused, where are the actual values of the "static variables" stored? I can find the names, but can't understand where the values are hidden.
Can somebody help me understand this?
You've run into one of the core truths of Smalltalk. Both of the following two statements are true: 1) Every object is an instance of some class. 2) Every class is an object. --- So, every class must be the instance of some class. What is the class of a class? Every time you define a class, you are actually defining a pair of classes -- the class, and another class to be the class of that class. The latter is known as a "metaclass" and it is always an instance of Metaclass. Each Metaclass has exactly one instance, which is a class. The class defines "instance-side" behavior and variables, and the metaclass defines "class-side" behavior and variables. This lets the same rules apply for both normal classes and metaclasses. For instance, every instance of a class contains a variable for each variable defined in its class. So if you define a named instance variable on a normal class, every instance of that class will contain its own copy of that variable. If you define a named instance variable in a metaclass, every instance of that metaclass will have its own copy of that variable. But metaclasses only have one instance, the class, so there's only one copy of that variable. Until you subclass that class. The instance-side instance variables are inherited, and so are the class-side instance variables. So you get a new metaclass that's a subclass of the old metaclass, and a new class that's a subclass of the class. This new subclass is distinct from its superclass, so it gets its *own* copy of the class instance variable, just like any other object. This is one way in which class instance variables are different from static variables. They're not really static at all, but they do have the lifetime of the class, just like any instance variable has the lifetime of the object it's in. And the usual rules of access to instance variables apply, which is why you need getter/setter methods if you want to access the variable from outside that class object. I hope this helps you understand Smalltalk a bit better. There are also class variables, which Nicolas mentioned, and which are quite different, and which are closer to static variables. Regards, -Martin
On Tue, Oct 4, 2016 at 4:23 AM, CodeDmitry <dimamakhnin@gmail.com> wrote:
I am trying to study Pharo's internals and I am now curious how it stores class variables.
I notice that in order to have a class `Greeter` with a "static" variable `greeting`,
I guess you are referring to... http://www.learncpp.com/cpp-tutorial/811-static-member-variables/ So its fair to analogize to a familiar concept, but you need to remember... Rule 1: *Everything* is an object. which includes class definitions, being instances of Metaclass. So try... Metaclass allInstances inspect. then select one and compare its 'methodDict' and 'thisClass' ==> 'methodDict' with what you see for that class in the System Browser. Notice the ClassDescription superclass to Metaclass has an instance variable 'instanceVariables'. Now one thing that confused me for a moment just now is, if you try... Metaclass allInstances select: [ :mc | mc instanceVariables size > 0 ]. then look at that instance variable 'instanceVariables' it is always nil due to the implementation in Pharo 5 of instance variables as Slots. In Pharo 4 you see actual names of instance variables. btw I'm curious now, does that ivar 'instanceVariables' planned to be removed some time? Now actually (IIUC) a C++ static member variable is most like a "Class Variable" which is defined on the instance side of a class. There are three main variable types to consider when defining a class in Pharo: Instance variables - scoped to instance methods, unique per instance Class Variables - scoped to instance methods & class methods, common to the class and all subclasses and all their instances Class Instance Variables - scoped to class methods, unique per class (i.e. instance of Metaclass) To experience the finer points of these you might try the experiment I describe here... http://forum.world.st/Class-vars-and-inst-vars-of-a-class-tp4749910p4749914....
I need to make `greeting` an instance variable under "show the class side" and create a "Getter" and "Setter" for this "instance variable".
First thing that confuses me is, why is this called an instance variable if this particular "static" method is not bound to any particular instance?
The method is bound to an instance of Metaclass, being the class definition. When you add methods or instance variables to the class-side in the Browser, you are adding them to this instance. There is one instance of Metaclass for each class in the system.
Is it just because it is defined in an "instance" of a "ProtoClass"?
I don't understand this question. Can you rephrase after doing the experiment linked above?
Second thing that confuses me is, where are these pairs of ("instance variable name" => "instance variable value") stored? I know that I can call
Transcript show: ((Greeter class) instanceVariables at: 1).
which prints "greeting".
and
Transcript show: Greeter instanceVariables class.
which prints "Array"(curious, i expected a Dictionary mapping Strings to Object).
What you are seeing is a copy of the core representation. Try debugging into.... (Greeter class instanceVariables at: 1) paying particular attention to... LayoutClassScope>>visibleSlots LayoutClassScope>>do:
Transcript show: ((Greeter class) instanceVariables at: 1) class.
prints "ByteSymbol".
Now I am confused, where are the actual values of the "static variables" stored? I can find the names, but can't understand where the values are hidden.
You are looking at a copy of the core representation. To work through a quick example... take the Morph class definition's first two instanceVariables: 'bounds owner...' and for each of their accessors #bounds and #owner right-click and choose <Inspect Method> then compare each [Bytecode] tab with the first line showing "callPrimitive: 264" or "callPrimitive: 265" respectively. These (and similar) primitives provide the *real* "compiled" access to the instance variables. So that demostration is the equivalent of asking "where are the values in variables stored" for C++ and reviewing its generated assembler code - although our VM provides a level of abstraction. Hopefully the ease of digging from source code down to its compiled bytecode demonstrates another aspect of the power of the Pharo environment. btw, you can see the list of VM primitives here... https://github.com/pharo-project/pharo-vm/blob/36079d9be14542ea9e0d72e5ef57b... cheers -ben
participants (7)
-
Ben Coman -
CodeDmitry -
Dimitris Chloupis -
Martin McClure -
Nicolas Passerini -
serge.stinckwich@gmail.com -
Udo Schneider