From: "Alek Storm" <[EMAIL PROTECTED]> Date: Thu, 12 Apr 2007 21:55:34 -0500
On 4/11/07, Allison Randal <[EMAIL PROTECTED]> wrote: > They might not clone their classes from the user perspective, but > internally it's the only truly safe way to modify a class that already > has objects instantiated (especially when you're talking about remove > operations). Otherwise, you have objects referencing attributes that > don't exist any longer in the class, or methods referencing attributes > that were never initialized in the object. The closest they can come is > the option 1) I listed. Whether it's safe or not, languages need the option of not cloning their classes. Therefore, Parrot needs it. We can't tell language implementors that we can't support their language because it's not "safe" . . . Now that I've finally read that part of the spec, it turns out that Lisp doesn't allow the class to be cloned when it is modified. And (as I mentioned earlier) it *does* require that modified instances be updated to reflect the new class definition. I am in the process of studying how CMUCL achieves this feat, which involves an intermediate data structure, and can post a summary if anyone is interested. As a result, I withdraw my statements in support of explicit cloning, and would prefer a solution that avoids *any* cloning. Any language whose class modifications affect already-instantiated objects would have its own way of resolving removed methods/attributes in find_method() or (get|set)_attribute(). True, but cross-language inheritance complicates the situation. If Language A permits radical class redefinition and exports ClassA, which is used as a superclass of ClassB in Language B that does not permit any redefinition, what should happen to ClassB instances when ClassA is redefined in a way that requires updating instances? Here are some possibilities: 1. Redefinition in ClassA is prevented, effectively propagating the Language B restriction up the inheritance chain. 2. ClassB instances are magically updated, because ClassB also inherits the Language A metaclass behavior. (This need not require Language B to permit class modification itself, since the propagation of changes to subclasses would need to be handled independently.) 3. ClassB is forbidden to inherit from ClassA at all, due to metaclass incompatibility. Since there aren't many formal constraints on inter-language inheritance, I think pretty much any behavior (short of segfaulting) could be argued to be correct. Furthermore, dynamic class redefinition is mostly useful in development, so this isn't a real use case; the ClassB developer is presumably using a packaged ClassA. Nevertheless, the implementor of Language B has a choice: Use the more fluid update semantics (which I hope is intended to be the Parrot default) and risk violating letter of the Language B spec, or restrict the update semantics and risk interoperability problems. Since the first choice is easier to implement, more helpful to users for debugging, and stands a good change of behaving as a compatible extension to the language, I know which I would pick. ;-} On 4/11/07, Bob Rogers <[EMAIL PROTECTED] > wrote: > Hmm. If a Lisp implementation ever worked this way, FWIW, it would be > considered buggy . . . You've hit the nail on the head. The problem is that Parrot can't assume that every language clones its classes. With solution 4, all classes are cloned, whether the language they belong to likes it or not. With the solution I proposed, LispClass would not clone itself on 'add_method', but ParrotClass would. Apart from the cloning issue, I submit that this would be buggy even for ParrotClass. Consider: 1. If 'add_method' always clones a ParrotClass, then autoloading methods would be self-defeating. (Maybe even class-defeating. ;-) 2. At some point later in the session, the user (who is developing in a Parrot language) will have some ParrotClass objects that support the new protocol, and some lying around that don't. I've been there, and can attest that this is a pain. To clarify, the 'instantiated' bit should be cleared on the newly-created clone, not on the original class, since cloning does not change the fact that it has instantiated objects. If that's what you meant, sorry, just making sure I understand you. Yes, exactly. No extra charge for double-checking. ;-} > The normal use case for this class-changing API, it seems to me, is to > redefine an HLL class definition incrementally by recompiling it. > Having one HLL mutate the class of another HLL seems relatively arcane. > Are you suggesting that this is a bad idea simply because it can be > abused in this manner? Yes. For example, code that deals with classes through their abstracted interface (good design from an OO standpoint) would have no idea which language they came from. It wouldn't be too common . . . Actually, now that I think about it, it's not arcane at all. Basic inheritance is enough to provide a natural mechanism for one language's class manipulation to affect the classes of another, just by normal redefinition. IMHO, that is all the more reason for Parrot to adopt the broadest practical functionality in ParrotClass, and to discourage language designers from dumbing it down. . . . Sorry for the length - couldn't help myself ;) Length shouldn't be something to apologize for. (I sure hope not; if it were, I'd be in trouble. ;-) -- Bob