This post was updated on .
CONTENTS DELETED
The author has deleted this message.
|
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 <[hidden email]> wrote: I am trying to study Pharo's internals and I am now curious how it stores |
This post was updated on .
CONTENTS DELETED
The author has deleted this message.
|
In reply to this post by CodeDmitry
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 |
In reply to this post by CodeDmitry
On Tue, Oct 4, 2016 at 4:23 AM, CodeDmitry <[hidden email]> 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.html > 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/36079d9be14542ea9e0d72e5ef57b596bd8aab52/mc/VMMaker.oscog.package/StackInterpreter.class/class/initializePrimitiveTable.st cheers -ben |
In reply to this post by CodeDmitry
On Tue, Oct 4, 2016 at 9:37 AM, CodeDmitry <[hidden email]> 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 <[hidden email]> a écrit : > >> On Tue, Oct 4, 2016 at 9:37 AM, CodeDmitry <[hidden email]> 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! > |
Free forum by Nabble | Edit this page |