[comp.lang.smalltalk] Smalltalk/V: adding new instance variable

ott@piyopiyo.hatori.t.u-tokyo.JUNET (ott) (06/16/89)

My second qustion today.

Using Smalltalk/V. Why is it not possible to add a new instance
variable to a class when it has already some?

I get the error message 'Has instance' and looking into the method in
question, it explicitly checks for that.

In the 86 version I got away with disabling this part, but the 286
version crashes with a violation error. I am sure its there for some
reason. 

What am I missing here?

Any help will be greatly appreciated as it annoys me very much.

Thanks

-max
------------------------------------------------------------------------------
Max Ott			     e-mail:
Hatori Laboratory             ott@piyopiyo.hatori.t.u-tokyo.junet@relay.cs.net
Dept. of E.E.; U of Tokyo             I am not a tourist, I live here, but
+(81)-(03) 812 2111 Ext. 6761         would not mind being one.

dclaar@hpcupt1.HP.COM (Doug Claar) (06/17/89)

Smalltalk/V seems to leave things laying around for various reasons. To get
rid of the instances, inspect object. Then inspect classPool. THEN, inspect
'Dependents' Your extra stuff will be there, as well as legitimate stuff.
Very carefully delete all the stuff that doesn't belong. 

Doug Claar
HP Computer Systems Division
UUCP: mcvax!decvax!hplabs!hpda!dclaar -or- ucbvax!hpda!dclaar
ARPA: dclaar%hpda@hplabs.HP.COM

cliff@ficc.uu.net (cliff click) (06/20/89)

In article <17@piyopiyo.hatori.t.u-tokyo.JUNET>, ott@piyopiyo.hatori.t.u-tokyo.JUNET (ott) writes:
> Using Smalltalk/V. Why is it not possible to add a new instance
> variable to a class when it has already some?
> 
> I get the error message 'Has instance' ...

If you have any instances of that class floating around and your trying to
add or delete fields from the instance Smalltalk would have to find each
occurance of objects of this class and "edit" them somehow to reflect the
new declaration for the class.  IMHO it should do this, keeping any 
original data that it can, tossing deleted fields and adding the new 
fields with nils - this won't be a fast operation, but it would be a darn 
sight more convenient than "Has instance".  

There is a way to get Smalltalk to put all of the objects which have a 
pointer to these instances in a dictionary.  You can then search each 
object in the dictionary looking for instances of your class in them, and 
replacing those instances with nil.  When you are done you will have 
destroyed all references to the class's objects, so those objects will go 
away, and you will no longer "have instances".

-- 
Cliff Click, Software Contractor at Large
Business: uunet.uu.net!ficc!cliff, cliff@ficc.uu.net, +1 713 274 5368 (w).
Disclaimer: lost in the vortices of nilspace...       +1 713 568 3460 (h).

trr@rayssd.ray.com (Terry R. Raymond) (06/22/89)

If you look at the description of user-defined primitives in the
Accessing Object within primitives section of the manual, you will
see that it states that the instance variables in the object are in
the same order in which they are defined by the class definition. 
The primitives access the variables by knowing the "offset".  If you
add a new variable it could easily cause an error with a primitive that
uses an instance variable.

Compiled smalltalk code is "probably" very similar.  I assume that when
a method references an instance variable the compiler compiles the 
reference as an offset.  Therefore, when a method, that has been recompiled
against a class definition that has a new instance variable, references
an old instance, one without the new variable, the reference may be wrong.

The moral is it can be difficult to add a new instance variable to a class
that has instances, or to a class that has a primitive that references
instance variables.
-- 
Terry Raymond
Raytheon Submarine Signal Division; Portsmouth RI; (401)-847-8000 x5597
------------------------------------------------------------------------------
Internet: trr@rayssd.ray.com    (trr%rayssd.ray.com@a.cs.uiuc.edu)
UUCP: {decuac,gatech,mimsy,mirror,necntc,sun,uiucdcs,ukma}!rayssd!trr

new@udel.EDU (Darren New) (06/22/89)

ParcPlace Smalltalk-80 will actually go out and edit the instances to
match the new declaration and then recompile all code that referenced
such instances.  It is smart enough to not do this when not needed.
E.g., it won't recompile when adding an instance variable at the
end of the list (or some such conditions). -- Darren

david@cullsj.UUCP (David Taylor) (06/24/89)

Welcome to Smalltalk/V's biggest headache.
I've found this the number one pain in an otherwise great system.
And let's face it - when you're prototyping you're going to run into this all
the time because you're constantly changing the class definition.
I'm not a Smalltalk guru, so I can't say why the user can't elect to propagate 
the new variable to existing instances. The only solution I've found is a messy
one; i.e. to unload, modify and reload the class:
	1 - Create a temporary class that has both the original and new instance
	    variables.
	2 - Transform all instances of the original class to become instances of 
	    the temporary class.
	3 - Remove the original class and create a new class of the same name
	    with the original and new instance variables.
	4 - Transform all instances of the temporary class to to become instances
	    of the new class. (Optionally) Remove temporary class.
Now I'm assuming that the new class must have the same name as the 
original. Otherwise, skip steps 3 and 4.
An example is in order. I don't have my Smalltalk/V book with me, so
I'll just have to pseudocode an example.
Assume we want to add a new instance variable, 'height', to class Human that
has instance variables 'weight' and 'age'.
	1 - Create class TempHuman. Add height, weight, and age to its instance 
	    variables. You can either do this manually by editing the class 
	    definition or do:
		TempHuman instVarNames: Human instanceVariableString, 'height'.
	2 - Human allInstances do: [ :each | each become: TempHuman ].
            "Now assign original values to variables of TempClass "
	    "Here I assume that methods exist to get/put instance variable values
	     and that those methods have the same name as the corresponding
	     variable"
	   Human instVarNames do: [ :aName | 
		TempHuman perform: aName with: (Human perform: aName) ].
	3 - Remove class Human. Then create class Human:
		Human instVarNames: TempHuman instanceVariableString
	4 - TempHuman allInstances do: [ :each | each become: Human ].
	    TempHuman instVarNames do: [ :aName |
                Human perform: aName with: (TempHuman perform: aName) ].
I believe instVarNames answers an Array of Symbol and instanceVariableString
answers a String of blank-seperated names, but I'm not sure.

PLEASE, PLEASE, PLEASE
if you find an easier way, let me know.

Thanks

P.S. I'm assuming that when you get the 'Has Instances' message that you don't
want to kill existing instances by saying
	Human allInstances [:each | each become: String new ]

rsimonian@x102c.harris-atd.com (Simonian RP 66449) (07/23/89)

In article <7030001@hpcupt1.HP.COM> dclaar@hpcupt1.HP.COM (Doug Claar) writes:
>Smalltalk/V seems to leave things laying around for various reasons. To get
>rid of the instances, inspect object. Then inspect classPool. THEN, inspect

OR, to get rid of all instances of a class FOO, evaluate:
	FOO allInstances do: [:i | i become: String new]

Richard P. Simonian     407/984-6006
Natural Language Processing Group
Harris GISD, Melbourne, FL  32902             
Internet: rsimonian%x102c@trantor.harris-atd.com

fchan@watvlsi.waterloo.edu (Francis Chan) (08/02/89)

In article <2225@trantor.harris-atd.com> rsimonian@x102c.harris-atd.com (Simonian RP 66449) writes:
>In article <7030001@hpcupt1.HP.COM> dclaar@hpcupt1.HP.COM (Doug Claar) writes:
>>Smalltalk/V seems to leave things laying around for various reasons. To get
>>rid of the instances, inspect object. Then inspect classPool. THEN, inspect
>
>OR, to get rid of all instances of a class FOO, evaluate:
>	FOO allInstances do: [:i | i become: String new]
>
>Richard P. Simonian     407/984-6006

Close. If FOO has subclasses and an instance of a subclass exists, then
you will get the walkback window.... Unfortunately it doesn't say which
subclass has the offending instance(s). So here's a blast'em all solution:

  FOO allSubclasses do: [ :sc |
      sc allInstances do: [ :i | i become: String new ]]

(I hope your code isn't copy righted, Richard :-)). I'm still not happy
with this though, since all we have done is made the instances into
instances of String. If you then follow up with a modification to any 
superClass of String, well ... you know what happens... more headaches.
There should be something to make the instances become nil (but we all know
that does not work all too well ...). 

P.S. If you are absolutely desparate (and I do mean desparate) do this:
  Scheduler reinitialize.
This will start you off with a nice clean slate... only the old Transcript
window will show up.

Francis Chan
SWEN
University of Waterloo

fchan@watvlsi.waterloo.edu (Francis Chan) (08/02/89)

>(sic) subclass has the offending instance(s). So here's a blast'em all solution:
>  FOO allSubclasses do: [ :sc |
>      sc allInstances do: [ :i | i become: String new ]]

OOPs! It's not quite a blast'em all. Don't forget to do
   FOO allInstances do: [ :i | i become: String new ]
as well.

Francis Chan
SWEN
University of Waterloo