I know that many on this list will be interested in the following TIP just propsed:
TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257
This is indeed based on xotcl, but it is *not* xotcl. There are good reasons for this overall (but not necessarily for each individual change ;) ). I would like xotcl users who are interested to please read this TIP carefully, but to bear a few items in mind:
1. We know that syntax will change. Some is terminology, and not all features are being adopted. This is not intended to be a TIP to include all of xotcl, but rather to provide a well featured oo:: base. itcl, snit and whatever isn't included from xotcl should be easily built on this base. At the same time, xotcl as an independent code base will continue to work just fine.
2. Not all Tcl users are OO lovers. Some are just OO agnostic and want to remain that way (like all the non-CS technical folks). For those who like OO, most come from OO worlds dominated by Java. Terminology that they will be familiar with is important. At the same time, we want to create the best system for Tcl (and Tcl is better than Java). The oo::tcl approach at least tries to address this without losing many of the benefits of XoTcl.
3. Megawidget support - whatever the solution it absolutely must be consistent with the goals of bringing a standard megawidget facility to Tk. I personally use snit::widget for this, with its delegation based system. I have not seen any other system come close to its ease of megawidget development (including xotcl based ones). Many of the large systems in Tcl are Tk-based, and they will benefit greatly from standardized OO. However, if the system isn't "Tk friendly", it will be rejected.
I'm sure there are lots of other good, pithy comments I could make, but I'll let you guys (and gals) digest the basics first.
Regards,
Jeff Hobbs, The Tcl Guy http://www.ActiveState.com/, a division of Sophos
On 26 Sep 2005, at 20:40, Jeff Hobbs wrote:
I know that many on this list will be interested in the following TIP just propsed:
TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257
First, I want to say I'm very excited about this TIP. If this goes into 8.5 I'd really like to see a big concentrated effort to get Tcl back on the map. Even Ruby is getting more press than Tcl right now and this needs to be changed. If Tcl includes an OO infrastructure with it then that might help with the push. It is essential we do not do this in a manner that says, "Me too", but to display the diversity and the elegance and power of Tcl. Tcl is a command-oriented language (instead of object-oriented), but that simple principle offers us ways to extend it in all kinds of directions. When a new paradigm appears, Tcl will be able to handle it too.
This is not Tcl going OO after many years of dilly-dallying, but providing a sound foundation which supports a wide range of extensions that have already existed. It's about making coders' lives easier.
I do have some comments on the TIP (no surprises there):
* The description about filters at the top of the TIP is not necessarily totally in line with XOTcl. Filters are not only about deciding whether a method is called but can also manipulate the message which is being passed. They can catch and do anything really.
* Mixins in XOTcl are classes which are dynamically mixed into the normal object inheritance chain. The mixins based on the TIP seem to be about mixing in procedures, which would be quite different.
* I disagree with the need for exported/non-exported methods. It adds complexity and for what? How is method lookup solved? Can sub-classes access non-exported methods? If not, wont that lead to problems for extensions? If they are seen, can they be overridden, even by accident, with public methods? Basically I see the whole business of private/public as mostly a documentation issue. There could be a mechanism in place for auto-generating docs on certain methods but not on others, but with no actual separation between the two. I believe Python follows this model to some extent. Convention versus forcing.
Besides, any mechanism such as the one described can be implemented by the use of filters. Filters offer much greater flexibility in this respect and finer granularity. I've never actually felt the need for public/protected/private/package.
* It is not true that XOTcl's creation mechanism makes it difficult to do Tk-like option handling.
The -dash arguments (or methods) are called before the constructor. The standard XOTcl way to do Tk-like options is to make the options into so-called parameters. Parameters are basically instance variables which have setter/getter methods attached to them. This leads to Tk-like option handling:
Class Car -parameter { {doors 5} }
set myCar [Car new -doors 3]
* I disagree with not making constructors methods. This is something I find to be a nuisance in Java. They act a bit like methods but aren't really methods. So I can't use normal inheritance rules to automatically get a constructor from a super-class. This is especially annoying with Exceptions which are often nothing more than a new classification and have no added functionality whatsoever. It also means a completely new mechanism needs to be in place for constructor introspection and manipulation. In XOTcl this is trivial as the constructor is a method like anything else.
Objective C uses the init method as a constructor (by convention) and does not cause problems. I've never heard of anyone trying to call [init] on an XOTcl object again. It all sounds a bit like a case of premature protection --- something which often bothers me. Protection makes a system more complex and often is not really needed. Protection hasn't ever been a theme in Tcl. Let the user and developer decide.
* Destructors. Same thing. Why? Why have something which adds complexity when a method can manage the same? With methods the implementation can decide whether to use the destructors further up (there might be cases when this is not desired), or in what order to apply its own cleanup and super-class cleanup.
I do agree that a [destroy] command might be a good idea. In fact, I'd go the whole way and stick it on the top level. I know [rename] can manage the same, but it's not totally obvious and then we'd have one mechanism that does the same for anything. Oh, and whatever the destructor does, I do believe it should not be allowed to prevent destruction of the object (unless the [destroy] command is manipulated).
* I agree with the class vs object method naming convention.
* Having instprocs named methods sounds like a good idea.
* What about child objects? XOTcl provides a mechanism where an object can be created as a child of another. If the parent object is destroyed, the child is automatically destroyed too. This is often useful and provides an alternative for one common area helped by garbage collection (as long as these child objects are never used anywhere else).
Kristoffer Lawson schrieb:
First, I want to say I'm very excited about this TIP. If this goes into 8.5 I'd really like to see a big concentrated effort to get Tcl back on the map.
hi folks,
a few words from our side: it's great news that more or less all of xotcl (modulo name changes) is contained in the TIP. This is the third version that i saw, and it improved from iteration to iteration. It has still a couple of errors, and what i think mis-conceptions (i mostly agree with kristoffer), and i would think that three more iterations, some deeper looks and some more discussions would have been a good idea.
However, there seem to be some reasons for the rush, and alltogether, the tip is far from being approved. The integration with the core would help to make things differnt as we did, being an extension. In many respects i would like to see a stronger conversion between xotcl and tcl, using objects as core entities replacing namespaces, or providing better interfaces to procs/methods etc, but this does not seem possible on the short range.
I am also not sure, what the TIP means for us, the xotcl core team; or whether the tcl core team will start implementing oo::tcl from scratch or mangling the xotcl code base. Some aspects of the TIP will change in the implementation process, i would expect an even stronger conversion, so it is hard to say what's left for pure xotcl.
It is certainly interesting for us to know, what you like most from the TIP. maybe it would be a good idea to make an xotcl workshop.
For the time being, we do business as usual, and improve xotcl. i think we have now the final version of xotcl 1.3.7, which should be out this week.
Kind regards -gustaf neumann
Jeff Hobbs wrote:
I know that many on this list will be interested in the following TIP just propsed:
TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257
This is indeed based on xotcl, but it is *not* xotcl. There are good reasons for this overall (but not necessarily for each individual change ;) ). I would like xotcl users who are interested to please read this TIP carefully, but to bear a few items in mind:
I feel slightly uneasy that debate about this TIP is occurring here and on the wiki, and yet notification of its existence hasn't even reached tcl-core yet. I have written some fairly substantial notes on the TIP at http://www.cs.nott.ac.uk/~nem/newoo.txt . These notes were supposed to be a post to tcl-core, but I don't want to further pre-empt the TIP publication.
I'm only an occassional XOTcl user, so my comments are aimed mostly at what I think would be consistent and useful for Tcl generally, and not consistency with XOTcl.
Anyway, many cheers to you all for kicking off this process.
-- Neil
On 26 Sep 2005, at 22:50, Neil Madden wrote:
Jeff Hobbs wrote:
I know that many on this list will be interested in the following TIP just propsed: TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257 This is indeed based on xotcl, but it is *not* xotcl. There are good reasons for this overall (but not necessarily for each individual change ;) ). I would like xotcl users who are interested to please read this TIP carefully, but to bear a few items in mind:
I feel slightly uneasy that debate about this TIP is occurring here and on the wiki, and yet notification of its existence hasn't even reached tcl-core yet. I have written some fairly substantial notes on the TIP at http://www.cs.nott.ac.uk/~nem/newoo.txt . These notes were supposed to be a post to tcl-core, but I don't want to further pre-empt the TIP publication.
Read through these commands. I probably agree on some points and disagree on others. I agree that the rationale behind [define] is fuzzy. I find the XOTcl model OK in that respect, but I don't have anything much against the TIP proposal either, and I do think it is a neat way of adding many methods in one go. Having syntax which attaches them to one another.
Oh, one area that the TIP does not discuss is that of extension via C. I would like to see a clean interface for creating classes, sub- classes and methods in C, if at all possible. Methods, in particular, would benefit from this as one could then begin to optimise critical parts of the code as it develops.
On Sep 26, 2005, at 1:36 PM, Kristoffer Lawson wrote:
Jeff Hobbs wrote:
I know that many on this list will be interested in the following TIP just propsed: TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257 This is indeed based on xotcl, but it is *not* xotcl. There are good reasons for this overall (but not necessarily for each individual change ;) ). I would like xotcl users who are interested to please read this TIP carefully, but to bear a few items in mind:
I feel slightly uneasy that debate about this TIP is occurring here and on the wiki, and yet notification of its existence hasn't even reached tcl-core yet. I have written some fairly substantial notes on the TIP at http://www.cs.nott.ac.uk/~nem/newoo.txt . These notes were supposed to be a post to tcl-core, but I don't want to further pre-empt the TIP publication.
Read through these commands. I probably agree on some points and disagree on others. I agree that the rationale behind [define] is fuzzy. I find the XOTcl model OK in that respect, but I don't have anything much against the TIP proposal either, and I do think it is a neat way of adding many methods in one go. Having syntax which attaches them to one another.
The point of [define] is simply that we want to be able to create objects which have a limited set of subcommands. Note that there's a distinct difference between writing an OO-API using a particular OO-framework for other users of that framework, and writing an object-style API for general users, many of whom might not care about the OO-framework at all. In the first case, you want to include all of the OO-framework's bells and whistles, because you expect your users to want to take advantage of them. In the latter case, you want to keep the API simple, clean, and easily documented.
[define] lets us do both. With [define] "instproc" and its siblings aren't subcommands of our objects--but at the same time, "instproc" and its siblings are available to every user who cares about them.
It's really an aesthetic issue rather than a technical issue; I find many OO APIs to be terribly cluttered (Java, I'm looking at *you*) such that it becomes hard to tell which methods are important amid all of the ones which are only occasionally of interest.
Will
------------------------------------------------------------- will -at- wjduquette.com | Catch our weblog, http://foothills.wjduquette.com | The View from the Foothills
On 27 Sep 2005, at 03:05, Will Duquette wrote:
It's really an aesthetic issue rather than a technical issue; I find many OO APIs to be terribly cluttered (Java, I'm looking at *you*) such that it becomes hard to tell which methods are important amid all of the ones which are only occasionally of interest.
I think this is a worthy sentiment and one I would subscribe to. [define] is definitely not a bad solution at all. It feels like a slot-based system. The aesthetics is why I'd prefer having constructors and destructors as real methods. Then they become really simple to describe. No specials required. Also, a Neil pointed out in his own notes, there are reasons why one would want to have assertions with destructors (and why not constructors too).
Will Duquette wrote:
The point of [define] is simply that we want to be able to create objects which have a limited set of subcommands. Note that there's a distinct difference between writing an OO-API using a particular OO-framework for other users of that framework, and writing an object-style API for general users, many of whom might not care about the OO-framework at all. In the first case, you want to include all of the OO-framework's bells and whistles, because you expect your users to want to take advantage of them. In the latter case, you want to keep the API simple, clean, and easily documented.
That's certainly a good goal.
[define] lets us do both. With [define] "instproc" and its siblings aren't subcommands of our objects--but at the same time, "instproc" and its siblings are available to every user who cares about them.
OK. The essential thing being done here then is to break down the grab-bag of methods defined in Class and Object into a bunch of different interfaces, so that clients of an object don't have to worry about a bunch of extra "proc" and "filter" etc methods that have nothing to do with their problem domain. I can sympathise with that. However, I'm not sure [define] is the right solution, as it just creates another bag of methods elsewhere (somewhat like [info] has become). We could simply change the methods to be class-methods of [class] and [object] (i.e. procs that expect an explicit self argument, rather than instance-methods). That way by default objects don't get lots of public methods that aren't needed by clients, but you can still do, e.g.:
class method myclass someproc {args} { ... } object method myobj ... object mixin myobj ...
This also somewhat reduces the need for self.method/method (or instproc/proc) distinction. Likewise, you could also use it for the script-style of define:
class define myclass { method foo ... method bar ... }
where these are interpreted as [class method myclass ...] and not [object method myclass ...].
It sort of clashes with previous XOTcl usage, where [class instproc] means define an instproc on the object "class", but if we change the name to "method" anyway then this is less of an issue. You could even leave access to the methods using the form:
myclass class method someproc ... myobj object method ...
which leaves only one top-level method in objects (two in classes). That seems a bit more OO-y, but I don't know if it really adds much.
-- Neil
On Sep 26, 2005, at 6:04 PM, Neil Madden wrote:
Will Duquette wrote:
The point of [define] is simply that we want to be able to create objects which have a limited set of subcommands. Note that there's a distinct difference between writing an OO-API using a particular OO-framework for other users of that framework, and writing an object-style API for general users, many of whom might not care about the OO-framework at all. In the first case, you want to include all of the OO-framework's bells and whistles, because you expect your users to want to take advantage of them. In the latter case, you want to keep the API simple, clean, and easily documented.
That's certainly a good goal.
[define] lets us do both. With [define] "instproc" and its siblings aren't subcommands of our objects--but at the same time, "instproc" and its siblings are available to every user who cares about them.
OK. The essential thing being done here then is to break down the grab-bag of methods defined in Class and Object into a bunch of different interfaces, so that clients of an object don't have to worry about a bunch of extra "proc" and "filter" etc methods that have nothing to do with their problem domain. I can sympathise with that. However, I'm not sure [define] is the right solution, as it just creates another bag of methods elsewhere (somewhat like [info] has become). We could simply change the methods to be class- methods of [class] and [object] (i.e. procs that expect an explicit self argument, rather than instance-methods). That way by default objects don't get lots of public methods that aren't needed by clients, but you can still do, e.g.:
Actually, I don't mind [info]. Yes, it's a bag of methods; but it's nice to have a rug to sweep things under, and it's even nicer to know *which* rug without having to think too much about it.
My only argument against this notion of yours and in favor of [define] involves implementing oo::snit on top of oo::. snit::types have typemethods, and just as I want a clean interface for my objects, I'd like a clean interface for my types as well.
If we abolished [define] and defined its methods as you describe, then oo::snit types would no longer have a clean interface. I could work around that by using an oo::object as a proxy for an underlying oo::class; I'd give the oo::object a create method that forwarded to the class, and then make the oo::object forward any user-defined typemethods as well.
The difficulty here is that an oo::snit::type wouldn't be an oo::class, then. And that's a problem, because Snit's two big problems are speed and lack of inheritance. If I'm going to go to the trouble of reimplementing Snit on top of oo:: I'd like to get both.
Other than that, I could go with your scheme. I kind of like [define], though. But then, naturally, I would. :-)
Will
class method myclass someproc {args} { ... } object method myobj ... object mixin myobj ...
This also somewhat reduces the need for self.method/method (or instproc/proc) distinction. Likewise, you could also use it for the script-style of define:
class define myclass { method foo ... method bar ... }
where these are interpreted as [class method myclass ...] and not [object method myclass ...].
It sort of clashes with previous XOTcl usage, where [class instproc] means define an instproc on the object "class", but if we change the name to "method" anyway then this is less of an issue. You could even leave access to the methods using the form:
myclass class method someproc ... myobj object method ...
which leaves only one top-level method in objects (two in classes). That seems a bit more OO-y, but I don't know if it really adds much.
-- Neil
------------------------------------------------------------- will -at- wjduquette.com | Catch our weblog, http://foothills.wjduquette.com | The View from the Foothills
Will Duquette schrieb:
OK. The essential thing being done here then is to break down the grab-bag of methods defined in Class and Object into a bunch of different interfaces, so that clients of an object don't have to worry about a bunch of extra "proc" and "filter" etc methods that have nothing to do with their problem domain. I can sympathise with that. However, I'm not sure [define] is the right solution, as it just creates another bag of methods elsewhere (somewhat like [info] has become). We could simply change the methods to be class- methods of [class] and [object] (i.e. procs that expect an explicit self argument, rather than instance-methods). That way by default objects don't get lots of public methods that aren't needed by clients, but you can still do, e.g.:
First of all, i do not like having define as it is for various reasons. But having define as an extra command is for an xotcl person not such a horrible thing, as long we have (inst)forward, which can bring it back into business with a one-liner. The other way around is more complicated.
But still, i think this issue is more than a matter of taste: here are a few arguments:
a) a more radical approach is to move all c-level commands out of object and class into one or more method repositories (similar to namespaces, but just a hash table containing for commands) and let the object system designer link these (private/public, if necessary) into the base classes of an object system. One can design a SnitClass or an XOTcl class or lsay a Java-kind class quite freely, and it provides room for incremental improvement without harming others.
b) We have discussed splitting xotcl classes into smaller components about two years ago. We did not do this mostly since xotcl users would most likely use Obect and Class as it is today.
Roughly and abstractly speaking, an xotcl class differs from an xotcl object by - providing a method repository (MR) for its instances - providing a life cycle management (LCM, factory with recycling) for its instances (create, alloc, configure, init, recreate, destroy, dealloc)
An xotcl object contains a data repository (DR) with an optional (from the implementation point of view) method repository for itself. Furthermore, objects are commands (which is to some respect nice, but makes it very hard to compete in speed with languages which have more lightweight objects such as Java).
A simplified picture of xotcl looks as follows:
XOTclObject = Cmd + DR + MR(self) XOTclClass = XOTclObject + LCM + MR(instances)
With mixins, a class can have multiple MRs for its instances, and an object can have multiple MRs for self.
Through various recent TIPs, Tcl namespaces are converging towards xotcl Objects. As Tcl provides data repositories both through namespaces and arrays. I would like to see a convergence here, providing maybe multiple "views" to the same "data model" (in the MVC terminology), allowing e.g. "array names" on namespaces/objects or the data store methods (e.g. set, unset, trace, ...) as overloadable methods on associative arrays and to provide a uniform interface for defining procs/methods/instprocs..., not having to use sometimes "proc", other times "define method". This issue of having slim interfaces continues certainly on the C level where different implementation for this isses bloat the code and makes it hard for the code to behave consistently.
Furthermore the bunch of info commands can be reduced by specifying in the info command the MR explicitely (using e.g. MR(method)), using e.g. one "info args", one rename method etc. for all methods/procs/instprocs/commands.
It would be certainly interesting to have the aspects described above as first class entities on the tcl layer and to provide composition functionalities for these similar to mixins for system designers.
Having said this, i am certainly not sure that "define" leads the right way by moving the methods to manipulate the MR to the top.
c) the concern with "clean interfaces" is certainly valid but addresses not only the number of methods, but as well orthogonality (so, define is neither orthogonal with tcl or xotcl). Providing a smaller interface can be achieved through good composition facilities (having the "right" superclasses, mixins) and hiding/protection (don't show helper methods, define explicit interfaces, making methods/variables private).
From earlier discussion about this TIP, i had the impression that this discussion is as well about "system matters" vs. "application matters". when one introspects an object, to see application issues (like submit, book, ...) rather than implementation nissues like being able to lappend to variables, etc. The point of view depends certainly on where one is doing the introspection, on the object (info methods is large) or on the class of the object with it instprocs. The documentation will be in most cases more on the class than on the object level, which will be a rather slick interface.
The TIP writers did not like the fact that general functionality is introduced in xotcl from Object (as it is in Ruby or Smalltalk or many other OO languages). I never found this a problem in real applications. i rather see problems with some low-level stuff, when it is not this way, when classes are destroyed, objects are reclassed, etc. I would feel better, when Object, Class are xtocl-like and and we provide some protection schemes through subclasses.
I am not going to repeat all earlier discussions here. Is it OK to send improvement proposals for the current TIP here, leaving aside this bigger issues?
-gustaf
Gustaf Neumann wrote:
a) a more radical approach is to move all c-level commands out of object and class into one or more method repositories (similar to namespaces, but just a hash table containing for commands) and let the object system designer link these (private/public, if necessary) into the base classes of an object system. One can design a SnitClass or an XOTcl class or lsay a Java-kind class quite freely, and it provides room for incremental improvement without harming others.
The TIP is (totally!) light on C-level API, largely because I've no idea what needs to go there. I'd even be happy (personally speaking) with an OO system that did not provide any C-level API at all. Other people will probably disagree. :-D
b) We have discussed splitting xotcl classes into smaller components about two years ago. We did not do this mostly since xotcl users would most likely use Obect and Class as it is today.
[...]
Having said this, i am certainly not sure that "define" leads the right way by moving the methods to manipulate the MR to the top.
Having the metadata manipulators outside the primary object hierarchy is pretty much a requirement, and it comes from what's needed for supporting multiple OO "looks and feels" on top. Whether it is a single command is quite negotiable as is the precise name of the command(s) of course.
c) the concern with "clean interfaces" is certainly valid but addresses not only the number of methods, but as well orthogonality (so, define is neither orthogonal with tcl or xotcl).
I admit it; I don't treat orthogonality as holy. It's nice, but it's not the only goal I have. :-)
[...]
The TIP writers did not like the fact that general functionality is introduced in xotcl from Object (as it is in Ruby or Smalltalk or many other OO languages). I never found this a problem in real applications. i rather see problems with some low-level stuff, when it is not this way, when classes are destroyed, objects are reclassed, etc. I would feel better, when Object, Class are xtocl-like and and we provide some protection schemes through subclasses.
Again, that's driven by supporting other OO systems too.
I am not going to repeat all earlier discussions here. Is it OK to send improvement proposals for the current TIP here, leaving aside this bigger issues?
The best place to discuss things is really the tcl-core mailing list.
BTW, I was wondering what happens when you do this in XOTcl (ignoring the syntax for now):
class A derived from Object defines instproc foo class B derived from A defines instproc bar class C derived from Object defines instprocs foo, bar and move
object D is a C with B mixed in call: D foo call: D move
Which implementation of foo gets called first? Which implementation of move gets called first?
Donal.
On 28 Sep 2005, at 18:49, Donal K. Fellows wrote:
The TIP is (totally!) light on C-level API, largely because I've no idea what needs to go there. I'd even be happy (personally speaking) with an OO system that did not provide any C-level API at all. Other people will probably disagree. :-D
Well yeah, I'd disagree in the sense that if any OO framework goes somewhere near the core, I'd like to see Tk being implemented in terms of it (or indeed any other C-based extension which uses objects). Not immediately, of course, but in the long run.
BTW, I was wondering what happens when you do this in XOTcl (ignoring the syntax for now):
class A derived from Object defines instproc foo class B derived from A defines instproc bar class C derived from Object defines instprocs foo, bar and move
object D is a C with B mixed in call: D foo call: D move
Which implementation of foo gets called first? Which implementation of move gets called first?
I believe C's foo gets called first, then A. There's only one definition of move so that's easy , C:)
On Sep 28, 2005, at 9:23 AM, Kristoffer Lawson wrote:
On 28 Sep 2005, at 18:49, Donal K. Fellows wrote:
The TIP is (totally!) light on C-level API, largely because I've no idea what needs to go there. I'd even be happy (personally speaking) with an OO system that did not provide any C-level API at all. Other people will probably disagree. :-D
Well yeah, I'd disagree in the sense that if any OO framework goes somewhere near the core, I'd like to see Tk being implemented in terms of it (or indeed any other C-based extension which uses objects). Not immediately, of course, but in the long run.
It would be nice to have a C-API; but I think it would be better to get the Tcl API stable first, and then rationalize the internals based on where we've gotten to before opening them up.
Will
------------------------------------------------------------- will -at- wjduquette.com | Catch our weblog, http://foothills.wjduquette.com | The View from the Foothills
Donal K. Fellows schrieb:
Gustaf Neumann wrote:
a) a more radical approach is to move all c-level commands out of object and class into one or more method repositories (similar to namespaces, but just a hash table containing for commands) and let the object system designer link these (private/public, if necessary) into the base classes of an object system. One can design a SnitClass or an XOTcl class or lsay a Java-kind class quite freely, and it provides room for incremental improvement without harming others.
The TIP is (totally!) light on C-level API, largely because I've no idea what needs to go there. I'd even be happy (personally speaking) with an OO system that did not provide any C-level API at all. Other people will probably disagree. :-D
i was not talking about the c api at all here. i was refering to the xotcl methods implemented in C (e.g. create, destroy, class, forward, mixin ...) being placed into a method repository (e.g. a namespace) maybe called ::xotcl::objcmds and ::xotcl::classcmds and then one can do e.g.
oo::class ::xotcl::Object -import public ::xotcl::objcmds::* oo::class ::xotcl::Class -superclass ::xotcl::Object -import public ::xotcl::classcmds::* ::xotcl::Class class ::xotcl::Object
while people proposing other OO-Systems can import stuff private/public to any kind of class hierarchy they want. In reality this will be more complicated, but you get the idea.
b) We have discussed splitting xotcl classes into smaller components about two years ago. We did not do this mostly since xotcl users would most likely use Obect and Class as it is today.
[...]
Having said this, i am certainly not sure that "define" leads the right way by moving the methods to manipulate the MR to the top.
Having the metadata manipulators outside the primary object hierarchy is pretty much a requirement, and it comes from what's needed for supporting multiple OO "looks and feels" on top.
hmm, what is a metadata manipulator? i was talking about more primitive c-level constructs which could help to make tcl (and its oo parts) more consistent. Read method repository (MR) as hash table of command pointer and data repository (DR) as hash table of variables. i would like to see a consitent interface to these as well in ca on the tcl layer and having these compontents in a better composable way. This would provide a much better basis for multiple OOs and a better integration with current tcl core (both ways)
The TIP writers did not like the fact that general functionality is introduced in xotcl from Object (as it is in Ruby or Smalltalk or many other OO languages). I never found this a problem in real applications. i rather see problems with some low-level stuff, when it is not this way, when classes are destroyed, objects are reclassed, etc. I would feel better, when Object, Class are xtocl-like and and we provide some protection schemes through subclasses.
Again, that's driven by supporting other OO systems too.
This can be solved by defining e.g. SnitClass having everything private except what it wants to publish.
I am not going to repeat all earlier discussions here. Is it OK to send improvement proposals for the current TIP here, leaving aside this bigger issues?
The best place to discuss things is really the tcl-core mailing list.
i have to figure out, where this is...
BTW, I was wondering what happens when you do this in XOTcl (ignoring the syntax for now):
class A derived from Object defines instproc foo class B derived from A defines instproc bar class C derived from Object defines instprocs foo, bar and move
object D is a C with B mixed in call: D foo call: D move
Which implementation of foo gets called first? Which implementation of move gets called first?
as kristoffer pointed out, there is only one move, so there is no ambiguity. In general the precedence order is per-object-mixins per-class-mixins self-procs class-hierarchy
The introspection command for this is D info precedence
-gustaf
Donal.
Gustaf Neumann wrote:
Donal K. Fellows schrieb:
BTW, I was wondering what happens when you do this in XOTcl (ignoring the syntax for now):
class A derived from Object defines instproc foo class B derived from A defines instproc bar class C derived from Object defines instprocs foo, bar and move
object D is a C with B mixed in call: D foo call: D move
Which implementation of foo gets called first? Which implementation of move gets called first?
as kristoffer pointed out, there is only one move, so there is no ambiguity.
There are two 'move' methods/instprocs. One is in the XOTcl base Object class, and one is in C.
In general the precedence order is per-object-mixins per-class-mixins self-procs class-hierarchy
The introspection command for this is D info precedence
Perhaps I should explain more about what I was asking about. :-)
What I did was I constructed the situation according to the attached diagram (sorry to everyone for doing an attachment, but I refuse to do ASCII art for this!) and what I wanted to know was, given that we've got a per-object mixin, would the foo inherited from A by B be mixed in at higher precedence than the foo gained by D directly from C. If that's the case, would the move inherited from Object through the mixin side override the move gained directly from C? As far as I can tell as someone who has not thought about this in detail, that's the only way to do this sort of thing consistently. But it also means that mixins will stamp all over any attempt to redefine behaviour for a particular application domain. If I'm wrong and I've overlooked something, what is it? It's certainly not clear to me. (Mind you, it's midnight as I write this so the old braincells might not be producing maximum clarity anyway. ;-) )
I hope this all explains why I was asking what appears to be on the surface a trivial question, and the answer should clear up the details of what I don't know about XOTcl inheritance rules from reading the documentation.
Donal.
Donal K. Fellows schrieb:
There are two 'move' methods/instprocs. One is in the XOTcl base Object class, and one is in C.
ok, i though this was already omitted :)
Perhaps I should explain more about what I was asking about. :-)
What I did was I constructed the situation according to the attached diagram (sorry to everyone for doing an attachment, but I refuse to do ASCII art for this!) and what I wanted to know was, given that we've got a per-object mixin, would the foo inherited from A by B be mixed in at higher precedence than the foo gained by D directly from C. If that's
the case, would the move inherited from Object through the mixin side override the move gained directly from C? As far as I can tell as someone who has not thought about this in detail, that's the only way to do this sort of thing consistently. But it also means that mixins will stamp all over any attempt to redefine behaviour for a particular application domain.
Look at the precedence order:
% D info precedence ::B ::A ::C ::xotcl::Object
therefore C->move before ::xotcl::Object->move
it would be no good idea to define this as you mentioned above ::B ::A ::xotcl::Object ::C
since e.g. on an "D destroy" the object would be deallocated though ::xotcl::Object and a destructor in C would never be called. Since every class is a subclass of ::xotcl::Object, mixin would not work in any useful way, at least when class hierarchies are mixed in. Mixing in single classes would be rather limited.
we call the mapping from the class structure to the order classes are searched "linearization". It takes care that the more general classes are not preceding subclasses.
If I'm wrong and I've overlooked something, what is it? It's certainly not clear to me. (Mind you, it's midnight as I write this so the old braincells might not be producing maximum clarity anyway. ;-) )
I hope this all explains why I was asking what appears to be on the surface a trivial question, and the answer should clear up the details of what I don't know about XOTcl inheritance rules from reading the documentation.
The follwing paragraph in the section "Precedence Order" in the tutorial is supposed to describe linearization. Sorry, if this is not clear enough:
Filters as well as classes (mixins and ordinary classes) are linearized. That means, each filter and each class can be only once on a precedence order list. If a filter or class can be reached more than once, the last occurrence is used.
best regards -gustaf neumann
Gustaf Neumann wrote:
The follwing paragraph in the section "Precedence Order" in the tutorial is supposed to describe linearization. Sorry, if this is not clear enough:
Filters as well as classes (mixins and ordinary classes) are linearized. That means, each filter and each class can be only once on a precedence order list. If a filter or class can be reached more than once, the last occurrence is used.
Hmm, I must have missed that somewhere. Please put this whole discussion down to trying to understand the linearization algorithm. Thanks for your patience!
Donal.
Am 26.09.2005 um 19:40 schrieb Jeff Hobbs:
TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257
First of all, this is a step in the right direction which should have been done *years* ago already. Many thanks to the creators of the TIP for their courage to open this can of worms again. I believe there will be many kudos *and* resistance from the user base of (all) OO systems luring arround in the Tcl community.
We are using XOTcl in a commercial MT-app already 5 years and, personally, I doubt that a (new) piece of software can reach the stability, performance and functionality of XOTcl in a reasonable time. Hey, since the proposal is based on XOTcl, why just not adopt XOTcl codebase? This would save lots of time and effort. I do understand that from syntactical point of view, some XOTcl pieces may/should be ommited or changed to satisfy C#/C++/Java folks, allright, but I believe this is easier done by taking the XOTCl codebase and tweak it, rather to write all from scratch.
I have skipped thru the TIP in fast forward mode (more detailed sweep is on the todo list) and one things jumped into my face:
Class::volatile: This feature is ommited
WHY FOR HEAVENS SAKE?
Seriously, the auto-garbage collection of objects is *crucial* for any serious use. It saves you awkward and error-prone constructs. Anybody doing any serious OO programming knows how complex the garbage-collection can be. I cannot imagine to live w/o this feature.
So, as said, more to come as I get more time to read the TIP in depth.
Cheers Zoran
Zoran Vasiljevic wrote:
Am 26.09.2005 um 19:40 schrieb Jeff Hobbs:
TIP #257: Object Orientation for Tcl http://www.tcl.tk/cgi-bin/tct/tip/257
First of all, this is a step in the right direction which should have been done *years* ago already. Many thanks to the creators of the TIP for their courage to open this can of worms again. I believe there will be many kudos *and* resistance from the user base of (all) OO systems luring arround in the Tcl community.
We are using XOTcl in a commercial MT-app already 5 years and, personally, I doubt that a (new) piece of software can reach the stability, performance and functionality of XOTcl in a reasonable time. Hey, since the proposal is based on XOTcl, why just not adopt XOTcl codebase? This would save lots of time and effort. I do understand that from syntactical point of view, some XOTcl pieces may/should be ommited or changed to satisfy C#/C++/Java folks, allright, but I believe this is easier done by taking the XOTCl codebase and tweak it, rather to write all from scratch.
to let the XOTcl folks know: this was just what I responded to the Tcl core folks when I saw the second version of the TIP. Some of the changes proposed are good ideas, others are just personal taste or syntactic sugar, while still others seem to be problematic from a conceptual point of view. I find it hard to discuss all these issues in one big step; to have a plan to do this is good -- and moving away from XOTcl's model is not a problem for me -- but doing all at once, all from scratch, without much experimentation will IMHO mean a long, long time until we have a stable OO language in the core, which will likely have only a mediocre object model design.
Im my opinion, the first step must be to make the Tcl core ready for OO, meaning to open the C implementation of Tcl namespaces with extension points for dispatching of subcommands (which will be methods in OO languages) and opening up the callstack for extensions. These are important conceptual considerations, which are not easily done, because a number of overlapping concepts need integration: objects, classes, namespaces, ensembles; and: callstack of Tcl, callstack of any OO extension, uplevel/upvar. Please note, this cannot be done without designing a dispatch model for the language (i.e. in XOTcl's model: the dispatcher bound to the object commands, self, and next), and the creation schemes/destruction orders of object/classes/namespaces must be aligned.
My point is: get these fundamentals of the object system right first, because once an official OO core extension is rolled out to the Tcl community, it might be too late to do fundamental changes. It seems natural to me, to use the existing XOTcl code base as a basis for experimenation and testing and do these changes to the core first, and once this is done, think about the details of the OO model. BTW, the issues mentioned above are the points where the new object system would benefit most from the integration with the core; due to missing extension points these are the points that are more cumbersome in XOTcl's C implementation. But at the moment, this is not addressed. In the TIP it is unclear: will these fundamentals work similar as in XOTcl or not? How is the plan to merge them with the core? At the moment, it is seems as though only a pure extension is planned, which is not a good idea in my point of view. Why not benefit from the core integration?
To answer two objections to my earlier post:
1) Backwards compatibility is not an issue here, because we're talking about pure extensions to the known Tcl concepts. Pure Tcl programs will run without changes. 2) I'm not at all talking about turning Tcl into an OO-only language. My point is that each namespace should have the capability to be lazy and automatically be turned into an object, so that there are no frictions to use objects and namespaces together. At the moment, each XOTcl object lazily aquires a namespace when it needs one, there's no reason, why this cannot be done the other way round, i.e. the namespace aquires its object command, when requested, or the namespace command is bound to a stub which intializes the object structure at first use.
Cheers,
Uwe
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