Hi everybody,
As others have pointed out the TIP is not easy to swallow and has to be digested in multiple courses, here is some partly feedback:
Some changes will be necessary. Certain aspects of XOTcl syntax are peculiar from a conventional OO point-of-view, and it is deeply unfortunate that a very large number of methods are predefined in the XOTcl base class.
It is common for the conventional OO view to define common behavior for all Objects in the top-Level class, look e.g. Ruby, Python, Smalltalk or Java. Certainly the common behavior changes from language to language. The "deeply unfortunate" does not seem appropriate.
Can you explain, more about the envisioned object system? I am confused about the TIP. It says:
Standard Metaclasses XOTcl defines two standard Metaclasses, xotcl::Object and
xotcl::Class....
This is not true, only xotcl::Class is a meta-class.
The new core object system will ... be ... based on the metaclasses oo::object and oo::class.
I am not sure whether there is a misconception about xotcl or about metaclasses in general. Since the TIP says:
meta-classes: These are subclasses of class, which permit more advanced customization of class behaviour.
which is partly true (except, that "class" is a metaclass as well (at least in xotcl) , furthermore, without a meta-class, one cannot create a class.
If the statement in the TIP is true (two basic meta-classes), some of the class diagrams are wrong. Another consequence is that the proposed object system can only create classes and no simple objects (every instance will be able to create new instances). This is quite interesting, xotcl can achieve this currently via providing Class as instmixin on Object. .... But most likely this was not intended.
filters: These are constraints (implemented in Tcl code, naturally) on whether a method may be called
if this is intended to describe, what filters in xotcl are, this is incorrect. If this is something different form xotcl, please explain. This description sounds more like a "guard" in xotcl.
In XOTcl, every class and every object has an associated namespace.
mostly true. Strictly speaking, xotcl allocates namespaces on demand. Namespaces are only allocated, when per-object procs or subcommands (e.g. nested objects) are added, since we need namespaces with tcl's c api as method repositories). If one uses objects with variables or using inherited methods, no namespace is allocated. So, the vast majority of objects in real life applications have no tcl-namespace. This lazy namespace allocates improves object allocation speed and - more important - saves a lot of memory (see space comparison of objects on the xotcl home page). Do you plan to change this?
The namespace associated with a class ::myclass is
::xotcl::classes::myclass;
This is as well only partly true. myclass has a lazy namespace like objects for procs or subobjects. It has as well a second namespace as method repository for its instances with the mentioned name (the variable part of the namespace is not used).
Since this section is called differences to xotcl: how is this intended in oo::tcl?
Exported procs appear as object subcommands; non-exported procs do not, but remain available as subcommands of the my command. In this way, the object itself can still use them, but they need appear in the object's interface only if desired.
you seem to mean this literally. even inside an object, you cannot call an private (non-exported) method by [self] p-method but only by my method why is this? i am not aware of any oo-language with such an restriction. or is this a misinterpretation?
.. oo::define
i have argued my concerns in length in an another mail.
... names: export and unexport.
i would call these rather "protected" and "public". Tcl's namespace exports are not about protection but about but about providing forwarders. One can call any tcl method of a namespace, no matter whether this is exported or not. This is conceptually different to the protection where some other object should not be able to call a protected method .
The TIP says:
oo::object name Constructs a new object called name of class oo::object; the object is represented as a command in the current scope. ... If name is the empty string, oo::object generates a name automatically that is guaranteed to not clash with any existing command name.
....
The new object has two predefined non-exported methods: eval and variable. Other subcommands and other behaviour can be added using oo::define
...
When an attempt is made to invoke an unknown method on any object, the core then attempts to pass all the arguments (including the command name) to the public unknown method of the object. If no such method exists, an error message is generated. Instances of the core oo::object class do not have an unknown method by default.
oo::class has the methods "create", "new" and "unknown"
just to be sure: oo::object is an instance of ::oo::class and has superclass oo::object (please make this in the TIP more explicit; please define instance-of relationships in the suggested class hierarchy to be clear about what is an instance of what?)
This raises a lot of questions:
- why you want to create an direct instance of oo::object. I would think, you won't.
- why has oo::define a "variable" method (i assume a new name for xotcl "instvar") when it has no set, append, etc, which are part of "struct"; i would assume that oo::object is designed so minimal that it cannot contain variables. i wonder, whether it makes sense to call "oo::object" object at all.
- while we are on this topic: is it intended that an oo::class instance cannot contain variables (oo::class has no class variables)?
- why is the description of what i believe is the behavior of the method unknown of oo::class part of the description of object? (what happens when you call "oo::object somename")
- why is there an alternate way to specify "new" (via empty strings) in the core? let users do this (e.g. via mixins) if they want it.
- why has oo::object no unknown. even namespaces have it nowadays. if i interpete correctly and one calls on an instance o1 of oo::object with the method "bar", then some built-in magic calls "o1 unknown bar"; if this is not defined, then "o1 unknown unknown bar" is called and the loop is detected? if the system calls internally "o1 unkown", then it is certainly part of the interface and should be defined and documented in oo::object.
- i did not see a "class" method; intended?
- what is the exact sequence of steps during object creation. i am not sure what you have in mind: how is the class assigned, when and how are the configuration parameters evaluated (since you dropped the configure method "deliberately")
I would suggest to drop the following sentence, which confuses me, since i would assume that the xotcl linearization should be left as it is.
Inheritance will follow the XOTcl pattern (except with a somewhat different class hierarchy, of course)
i am running out of time now, two simple questions:
next The next command allows methods to invoke the implementation of the method with the same name in their superclass (as determined by the normal inheritance rules; if a per-object method overrides a method defined by the object's class, then the next command inside the object's method implementation will invoke the class's implementation of the method). The arguments to the next command are the arguments to be passed to the superclass method; this is in contrast to the XOTcl next command, but other features in Tcl 8.5 make this approach viable and much easier to control. The current stack level is temporarily bypassed for the duration of the processing of the next command; this is in contrast to the XOTcl version of the next command, but it allows a method to always execute identically with respect to the main calling context.
I try to extract the differences to "next" in xotcl,
- one difference is that one has now to specify the argument list (i don't see the advantage) - "executing in the same callframe" seems a problem to me. what happens with upvar, uplevel, debuggers? some of the information like the current class are kept on the stack. How will this be realized? after next the calling proc continues in the original frame. how will this work?
why is next changed? have i interpreted something wrong?
It is an error to invoke the next command when there is no superclass definition of the current method.
What is a superclass definition of a method? Should i read this as "an error is issued when next is called on non-shadowed methods"? This would make it quite ugly to write generic interceptors, since all next calls have to be wrapped in "catch"es.
concerning self: when i see correctly, - a few subcommands were folded into complexer ones returning more information (e.g. "self caller" is essentially "[list [self calllingobject] [self callingclass] [self callingproc]]") which makes it slower to produce and consume this info, especially, when only a part of this is needed. These infos are mostly used in speed sensitive situations such as filters or debuggers or tracecs, which call these commands frequently.
- a few subcommands are removed (info for transparency for interceptors, isnextcall). Why is this? Is your plan to drop this?
- a few new subcommands "self object" (equivalent to "self", why is this needed?) and "self namespace" (2 comments about "self namespace": self returns in general information about incovation records on the callstack, so this subcommand should not be there; why is this needed at all, when objects are namespaces?)
best regards -gustaf neumann