invoking a *class* method from a workspace

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

invoking a *class* method from a workspace

mstram-2
What's the trick / catch ... if there is one for invoking a class method from a workspace?

I created a Class "MikeTest".

- Added an instance method :   "imethod"

MikeTest >> imethod
        ^ 'I am an instance method'

- Added a Class method

MikeTest class>>cmethod
       ^ 'I am a class method'

----
Then in a workspace :

t := MikeTest new.
t imethod  (alt-p)  -->>  'I am an instance method'   (As expected)

t cmethod (alt-p)   gives 'MessageNotUnderstood'

http://mstram.freepgs.com/img/message_not_understood_when_evaluating_class_method.jpg

The debug trace has 'UndefinedObject>>Doit' ... which seems strange to me ... does that mean
the workspace doesn't understand how to send a class method ???

Puzzled (again).

Mike
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Edgar J. De Cleene



El 5/26/07 9:50 AM, "mstram" <[hidden email]> escribió:

>
> What's the trick / catch ... if there is one for invoking a class method from
> a workspace?
>
> I created a Class "MikeTest".
>
> - Added an instance method :   "imethod"
>
> MikeTest >> imethod
>         ^ 'I am an instance method'
>
> - Added a Class method
>
> MikeTest class>>cmethod
>        ^ 'I am a class method'
>
> ----
> Then in a workspace :
>
> t := MikeTest new.
> t imethod  (alt-p)  -->>  'I am an instance method'   (As expected)
>
> t cmethod (alt-p)   gives 'MessageNotUnderstood'
>
> http://mstram.freepgs.com/img/message_not_understood_when_evaluating_class_met
> hod.jpg
>
> The debug trace has 'UndefinedObject>>Doit' ... which seems strange to me
> ... does that mean
> the workspace doesn't understand how to send a class method ???
>
> Puzzled (again).
>
> Mike


do MikeTest cmethod.

Edgar


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Klaus D. Witzel
In reply to this post by mstram-2
Hi mstram,

on Sat, 26 May 2007 14:50:34 +0200, you wrote:

> What's the trick / catch ... if there is one for invoking a class method  
> from
> a workspace?
>
> I created a Class "MikeTest".
>
> - Added an instance method :   "imethod"
>
> MikeTest >> imethod
>         ^ 'I am an instance method'
>
> - Added a Class method
>
> MikeTest class>>cmethod
>        ^ 'I am a class method'
>
> ----
> Then in a workspace :
>
> t := MikeTest new.
> t imethod  (alt-p)  -->>  'I am an instance method'   (As expected)
>
> t cmethod (alt-p)   gives 'MessageNotUnderstood'
>
> http://mstram.freepgs.com/img/message_not_understood_when_evaluating_class_method.jpg
>
> The debug trace has 'UndefinedObject>>Doit' ... which seems strange to me
> ... does that mean
> the workspace doesn't understand how to send a class method ???

The line with UndefinedObject>>DoIt is how the compiler invokes the  
expression when you do (alt-p). When you select that line, you can see  
your expression decompiled. So, no problem.

The other question was answered by Edgar.

/Klaus

> Puzzled (again).
>
> Mike


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Bert Freudenberg
In reply to this post by mstram-2
On May 26, 2007, at 14:50 , mstram wrote:

> What's the trick / catch ... if there is one for invoking a class  
> method from
> a workspace?

"Class methods" in Smalltalk are regular methods, because classes are  
regular objects. Unfortunately the browser gives the impression that  
there are two kinds of methods ...

        MyClass new

simply sends #new to the object MyClass. This is how you invoke a  
"class method".

Remember, anything in Smalltalk is an object. Even classes. There is  
not even a "syntax" to define a class or a method (just like there is  
no syntax for control structures). Everything is accomplished by  
sending messages.

- Bert -



_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

mstram-2
In reply to this post by Edgar J. De Cleene
Edgar J. De Cleene wrote
do MikeTest cmethod.
Ok thx, have it working now.

Though I ran into an error when I tried to use :

do MikeTest cmethod.

and changed it to just

MikeTest cmethod.

:)

also :

avar := MikeTest cmethod

also works, as I'm sure you know .. but took me a minute to think of ;)

Mike

Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

mstram-2
In reply to this post by Bert Freudenberg
Well obviously I need to a lot more reading and experimenting with this,
even if  "class" methods are "regular" methods, there is something different
with them as far as :

1) the syntax to access them  ("fire" .. "call" .. "invoke" ??? what is the traditional term ? )

2) At least one difference I've found is that I when tried to create a "class" method that accessed an instance variable, Squeak warned that the variable didn't exist and asked if I wante to create it (is this a bug?) ... even though it was "declared" in the class definition.

I tried modifying my MikeTest to :

Object subclass: #MikeTest
        instanceVariableNames: 'ivar1'
        classVariableNames: 'Cvar1'
        poolDictionaries: ''
        category: 'Mike1'

and adding :

A) -----------"instance method " -------------------------------

imet: ivar icmet: cvar
        ivar1 := ivar.
        Cvar1  := cvar.
        ^ 'I am an instance method'
---------------------------------------------

iget
  |temp|
     temp := Dictionary new.
     temp at: 'ivar1' put: ivar1.
     temp at: 'cvar1' put: Cvar1.
     ^ temp.

and

B)   --------------"class method " --------------------------------
cmet: ivar ccmet: cvar
        ivar1 := ivar.
          Cvar1  := cvar.
         
          Cvar1  := cvar.
     ^ 'I am a Class Method'
--------------------------------------------------------------
cget
  |temp|
     temp := Dictionary new.
     temp at: 'cvar1' put: Cvar1.
    temp  at: 'ivar1' put: ivar1.
     ^ temp.
=================================


(I realize 'iget' and 'cget' are the same thing, I just wanted to see if there is any difference when running them.)

But Squeak says that 'ivar1' is undeclared and asks if I want to declare it.  It accepts it being declared as an instance variable (even though it already was according to the class definition ... (is this a bug?).

I can set / retrieve the variables with either the "class" or "instance" methods, so I'm not sure why Classes have been setup in Squeak using both types of methods.

t1 := MikeTest new.

result := MikeTest cmet: 'Class method setting inst var ivar1-> inst44'  ccmet: 'Class method setting class var Cvar1 -> Class01'


Bert Freudenberg-2 wrote
On May 26, 2007, at 14:50 , mstram wrote:

> What's the trick / catch ... if there is one for invoking a class  
> method from
> a workspace?

"Class methods" in Smalltalk are regular methods, because classes are  
regular objects. Unfortunately the browser gives the impression that  
there are two kinds of methods ...

        MyClass new

simply sends #new to the object MyClass. This is how you invoke a  
"class method".

Remember, anything in Smalltalk is an object. Even classes. There is  
not even a "syntax" to define a class or a method (just like there is  
no syntax for control structures). Everything is accomplished by  
sending messages.

- Bert -
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Bert Freudenberg

On May 26, 2007, at 18:32 , mstram wrote:

>
> Well obviously I need to a lot more reading and experimenting with  
> this,
> even if  "class" methods are "regular" methods, there is something  
> different
> with them as far as :
>
> 1) the syntax to access them  ("fire" .. "call" .. "invoke" ???  
> what is the
> traditional term ? )


There is no special syntax. The only difference is the receiver.  
Either you send a message to an instance of a class or or the class  
itself (which, as mentioned before, is a regular object).

> 2) At least one difference I've found is that I when tried to create a
> "class" method that accessed an instance variable,

Instance variables are private, they can only be accessed by the  
object itself. So from the class object you cannot access instance  
variables of one of its instances.

> Squeak warned that the variable didn't exist and asked if I wante  
> to create it (is this a bug?) ...
> even though it was "declared" in the class definition.
> [...]
> But Squeak says that 'ivar1' is undeclared and asks if I want to  
> declare it.
> It accepts it being declared as an instance variable (even though  
> it already
> was according to the class definition ... (is this a bug?).

No, what you did there is you defined 'ivar1' as an instance variable  
of the class object itself, not for instances of your class. It will  
be listed in the browser when you switch to the class side  
definition. This feature is very rarely used.

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

K. K. Subramaniam
In reply to this post by mstram-2
On Saturday 26 May 2007 10:02 pm, mstram wrote:
> 2) At least one difference I've found is that I when tried to create a
> "class" method that accessed an instance variable, Squeak warned that the
> variable didn't exist and asked if I wante to create it (is this a bug?)
> ... even though it was "declared" in the class definition.
Mike,

Think of instantiation and declaration as being like icecream and its récipé.
You can make many cups of icecreams from the same récipé. The instance
variable (cherry) declared in the class definition (récipé) will be created
only when a object of this class is created (icecream pie). You cannot assign
to an instance variable in a class method anymore than you can eat cherries
from a récipé :-). You 'browse' a récipé and 'inspect' or 'explore' the
icecream :-).

This analogy doesn't apply exactly to Squeak. Since classes are also objects
that are created when you 'accept' the definition (except that its variables
are created from classVariableNames), so you can use them in class methods
immediately. Like Bert explained in an earlier mail, use of classVariables is
very rare.

Enjoy .. Subbu
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Bert Freudenberg
On May 27, 2007, at 17:14 , subbukk wrote:

> Since classes are also objects
> that are created when you 'accept' the definition (except that its  
> variables
> are created from classVariableNames), so you can use them in class  
> methods
> immediately.

Not quite. Those variables are "class variables", which are global  
variables (global to the class and subclasses and all their  
instances). Their names start with a capital letter like every global  
variable in Smalltalk.

> Like Bert explained in an earlier mail, use of classVariables is
> very rare.

There is a difference between "class variables" (which are like  
"static" variables in other systems, so they get their fare share of  
use) and "class instance variables" (very rarely used indeed). You  
see "class instance variables" only when you switch the browser to  
the class side. "Class instance variables" have a different value in  
each subclass and are private to the class-side. Hence they are not  
global and have lower-case names.

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

K. K. Subramaniam
On Sunday 27 May 2007 9:44 pm, Bert Freudenberg wrote:
> There is a difference between "class variables" (which are like
> "static" variables in other systems, so they get their fare share of
> use) and "class instance variables" (very rarely used indeed). You
> see "class instance variables" only when you switch the browser to
> the class side. "Class instance variables" have a different value in
> each subclass and are private to the class-side. Hence they are not
> global and have lower-case names.
Thank you for explaining this in detail. I missed the fact that instance
variables listed by browser on the class side are different from those on the
instance. If I understood this correctly:
 (class instance) variables - variables global to all objects instantiated
from a class

 class (instance variable) - instance variable of the class (treated as an
object and therefore visible only to its methods and methods in its
subclasses).

BTW, I used the code below to inspect classes with explicit CIVs:
(Smalltalk values select: [ :c |
                (c isKindOf: Class) and: [c class allInstVarNames size > 13 ] ])
                        collect: [ :d | { d . d class allInstVarNames size} ]

but this gave me classes that inherit them too. Is there a way to tease out
classes that  *define* CIVs?

Regards .. Subbu
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Scott Wallace-2
Hi, Subbu,

Try:

ClassListBrowser browseClassesSatisfying: [:cl | cl class  
instVarNames size > 0] title: 'classes defining class-side inst vars'

Cheers,

   -- Scott


On Jun 4, 2007, at 10:40 AM, subbukk wrote:

> BTW, I used the code below to inspect classes with explicit CIVs:
> (Smalltalk values select: [ :c |
> (c isKindOf: Class) and: [c class allInstVarNames size > 13 ] ])
> collect: [ :d | { d . d class allInstVarNames size} ]
>
> but this gave me classes that inherit them too. Is there a way to  
> tease out
> classes that  *define* CIVs?
>
> Regards .. Subbu
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://lists.squeakfoundation.org/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Bert Freudenberg
In reply to this post by K. K. Subramaniam

On Jun 4, 2007, at 19:40 , subbukk wrote:

> On Sunday 27 May 2007 9:44 pm, Bert Freudenberg wrote:
>> There is a difference between "class variables" (which are like
>> "static" variables in other systems, so they get their fare share of
>> use) and "class instance variables" (very rarely used indeed). You
>> see "class instance variables" only when you switch the browser to
>> the class side. "Class instance variables" have a different value in
>> each subclass and are private to the class-side. Hence they are not
>> global and have lower-case names.
> Thank you for explaining this in detail. I missed the fact that  
> instance
> variables listed by browser on the class side are different from  
> those on the
> instance. If I understood this correctly:
>  (class instance) variables - variables global to all objects  
> instantiated
> from a class

This sounds more like "class variables".

>  class (instance variable) - instance variable of the class  
> (treated as an
> object and therefore visible only to its methods and methods in its
> subclasses).

I don't think that is correct - what do you mean by "treated as an  
object"? I may be repeating myself, but *everything* is "treated as  
an object", because it is.

There really is only a difference between local and global variables.  
Local vars are lowercase by convention and local to an object  
instance ("instance variables") or a method activation ("temporary  
variables", "arguments"). There are special byte codes to access  
them. Global variables are uppercase by convention and are actually  
Associations (key->value pairs) held in dictionaries known to the  
compiler, and the Association gets stored as literal in a  
CompiledMethod. Their "globalness" differs in what dictionary  
("variable pool") they live in - the one called "Smalltalk", or the  
"classPool" inst var of classes (these are "class variables"), or in  
shared pools (pools that are listed in the "sharedPool" class inst  
var, or whatever other dictionaries where given to the compiler (like  
"References" for etoys scripts).

> BTW, I used the code below to inspect classes with explicit CIVs:
> (Smalltalk values select: [ :c |
> (c isKindOf: Class) and: [c class allInstVarNames size > 13 ] ])
> collect: [ :d | { d . d class allInstVarNames size} ]
>
> but this gave me classes that inherit them too. Is there a way to  
> tease out
> classes that  *define* CIVs?

Smalltalk allClasses select: [:ea | ea class instVarNames size > 0]

So one of them is Beeper. Just do a "Beeper inspect" to see its class  
inst vars, or to see which superclass defines what, do:

Beeper class withAllSuperclasses collect: [:ea | ea -> ea instVarNames]

an OrderedCollection(
        Beeper class->#('default')
        Object class->#()
        ProtoObject class->#()
        Class->#('subclasses' 'name' 'classPool' 'sharedPools' 'environment'  
'category')
        ClassDescription->#('instanceVariables' 'organization')
        Behavior->#('superclass' 'methodDict' 'format')
        Object->#()
        ProtoObject->#()
)
       


- Bert -



_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

K. K. Subramaniam
On Tuesday 05 June 2007 1:21 am, Bert Freudenberg wrote:
> >  class (instance variable) - instance variable of the class
> > (treated as an
> > object and therefore visible only to its methods and methods in its
> > subclasses).
>
> I don't think that is correct - what do you mean by "treated as an
> object"? I may be repeating myself, but *everything* is "treated as
> an object", because it is.
In Smalltalk, classes are first order objects. I need to keep reminding myself
about this :-) because in many imperative languages this is not true.

> Smalltalk allClasses select: [:ea | ea class instVarNames size > 0]
Thanks for this hint. This is what I needed:
Smalltalk allClasses select:  [ :c | c class instVarNames size > 0 ]
thenCollect: [ :c | c -> c class instVarNames ].

I had dropped the 'class' method and instVarNames didn't work. No wonder.
28 classes out of 2043 define their own instance variables. Rare indeed!

Thanks a lot .. Subbu
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: invoking a *class* method from a workspace

Bert Freudenberg

On Jun 5, 2007, at 7:55 , subbukk wrote:

> On Tuesday 05 June 2007 1:21 am, Bert Freudenberg wrote:
>>>  class (instance variable) - instance variable of the class
>>> (treated as an
>>> object and therefore visible only to its methods and methods in its
>>> subclasses).
>>
>> I don't think that is correct - what do you mean by "treated as an
>> object"? I may be repeating myself, but *everything* is "treated as
>> an object", because it is.
> In Smalltalk, classes are first order objects. I need to keep  
> reminding myself
> about this :-) because in many imperative languages this is not true.
>
>> Smalltalk allClasses select: [:ea | ea class instVarNames size > 0]
> Thanks for this hint. This is what I needed:
> Smalltalk allClasses select:  [ :c | c class instVarNames size > 0 ]
> thenCollect: [ :c | c -> c class instVarNames ].
>
> I had dropped the 'class' method and instVarNames didn't work. No  
> wonder.
> 28 classes out of 2043 define their own instance variables. Rare  
> indeed!

And even of these few, some are in error and should really be class  
vars instead.

- Bert -


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners