On 4/11/07, Bob Rogers <[EMAIL PROTECTED]> wrote:
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.
"find_class" returns whatever is currently registered as the class. A
class-modifying method doesn't change that; it just returns the cloned
class PMC. If the HLL wants to register the modified version, it can
do so, but I'm not in favor of a separate class registry, and I've
heard it's going away anyway. In any case, it should be left up to
the HLL what it wants to do with the modified class, since one
approach doesn't work with all languages.
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)?
Of course add_method's create new classes; the implementation of that
is what we've been talking about. We want the class to be modified,
but already-instantiated objects keep their reference to the class
they were created with. Allocating a new class for every add_method,
add_attribute, etc. is a downside when there are several in a row and
all we want is the end result, but I've already proposed a solution to
that: create a shortcut method that takes a list or slurpy of
attributes to add, so it's all done at once.
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.
That's a great idea, and is probably better than my shortcut method
idea; we'll have to see what others think. But I'm not sure why
remove_* would be any different than add_* - they create a clone of
the class, and remove the attribute. Instantiated objects of the
class don't notice a thing.
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.
Not all languages want to clone their classes on modification. These
languages would use their own class PMCs that don't clone themselves.
If one of their classes is passed to and cloned by a different HLL,
their class system will be screwed up/inconsistent. I'm not sure how
requiring HLLs to deal with explicit cloning would be simpler than
having it abstracted away. This system is much more flexible.
Error recovery would also be easier for explicit cloning; what happens
if one of the class-mutating methods throws an error?
I'm afraid you lost me. How would this be different? Could you
provide some more information?
--
Alek Storm