From: "Alek Storm" <[EMAIL PROTECTED]> Date: Wed, 11 Apr 2007 00:02:29 +0000
On 4/10/07, Allison Randal <[EMAIL PROTECTED]> wrote: > 4) Do away with automatic morphing. Attempting to make changes to a > class that's already been instantiated is not allowed (add_method, etc. > will throw an exception). This also eliminates the need for > remove_method, remove_attribute, remove_role, and remove_parent. To > modify a class that has instantiated objects you must clone it first: > > classobj = newclass 'Foo' > object = classobj.'new'() > > newclassobj = classobj.'clone'('exclude_methods'=>$P1) > newclassobj.'add_method'('bar', $P3) > object2 = newclassobj.'new'() > > And 'clone' could take an option specifying whether this particular > clone will replace the existing class in the namespace. Disadvantage: It > eliminates some of the DWIMery of the system. On the other hand, it > might make it easier to implement a language that doesn't allow > modifications to instantiated classes. (This is currently my favorite > alternative.) > > Allison I like this one, but I also have another alternative. First, make all class-modification code (add_method, remove_attribute, etc) return a PMC*. Whenever one of these methods is called on a class, the class is cloned . . . What does "find_class" return after one of these? If it returns the new class, then there is no need for the class-mutating ops to do so, except possibly for convenience. classobj = newclass 'Foo' object = classobj.'new'() # add_method returns a clone of the original class with "bar" added # C<object> keeps its reference to the original class classobj = classobj.'add_method'('bar', $P3) object2 = classobj.'new'() Surely you are not suggesting that any random "add_method" should require creating a new class? Did you mean "add_attribute" (or whatever)? The only downside I can think of is the overhead involved in creating a new clone of the class for every change to it, for example, when many attributes are added at once . . . This is not necessary; you only need to clone the class after the first time it is instantiated. So you can put an "instantiated_p" flag in the class to keep track, and keep mutating the same new class until the next instantiation. The remove_* operations could stay, they would just throw errors on instantiated classes. But in that case, it might be simpler for HLL code to stick to Allison's original alternative 4, i.e. make an explicit clone, mutate it as required, and then install it as "the" class returned by find_class. Error recovery would also be easier for explicit cloning; what happens if one of the class-mutating methods throws an error? Sorry if this is misplaced; I haven't been paying a whole lot of attention to objects. -- Bob Rogers http://rgrjr.dyndns.org/