TIP #257 Discussion

Extracted from TIP #257: Object Orientation for Tcl to separate facts from discussion.

escargo 26 Sep 2005 -

Discussing basic requirements should come first. Then the rationale for your proposal to meet those requirements. Unless people agree on the basic requirements, other discussions are subject to debate.

How about public and private versus export and unexport? The circumlocutions you need to use to describe, for example, non-exported methods, seems less clear than calling them private.

JH: I prefer public and private as well, and it was mentioned already to DKF, but the key is that private is in terms of not being exported, rather than C++-like private.

DKF: I'm not religiously attached to the names FWIW.

escargo - We can only look to other languages for guidance to a limited degree. Java has its own definitions for public and private (as well as protected and implicitly of package scope). Just as other languages have namespaces, Tcl can have public/private within its own framework without requiring them to be identical to similar terms in other languages.

escargo 3 Oct 2005 - What about methods that are neither exported nor unexported? How similar would this export be to namespace export in that regard? (Which, if I understand correctly means that anything that is not exported is not visible outside the namespace by ordinary means.)

Brian Theado - The tip states: Note that this TIP does not propose to actually include any XOTcl (or Itcl or Snit or ...) compatability packages in the core; it is about forming a foundation on which they can be built (which happens to also be a comparatively lightweight OO system in itself). Such compatability packages can either remain separate code, or be the subject of future TIPs.

Will implementation of the tip make it reasonable for at least these three to have compatibility packages implemented in pure Tcl? I guess for snit the answer is easy since it is already pure Tcl. With XOTcl, the pieces left out by the TIP are likely easy to implement with plain Tcl? And for Itcl, Itcl in XOTcl says that the XOTcl based emulation is faster than Itcl?

LV Brian, what are you thinking of when you say "compatibility packages"?

Brian Theado - The term "compatibility packages" came from the tip itself and as I understand it, it is code built using the oo::object and oo::class commands proposed by the tip. The compatability package for XOTcl would allow existing XOTcl dependent code to run without change. Same for ITcl and Snit.

JH: It is possible that the rest of these packages can be done in pure Tcl (of course for SNIT, maybe for the others).

SRIV Even if this OO system can't make megawidgets directly, as long as a tcl wrapper on top of the OO could be made to create megawidgets, I'll be happy.

Are there any OO packages right now which cannot be the basis of a megawidget strategy? I mean, itcl has itk and iwidgets. Snit has snidgets. I don't know - has anyone did serious work on XOTcl megawidgets?

SRIV My definition of megawidgets are those created in pure tcl/tk that behave identical to stock tk widgets, in that the configure command returns a list of available options and that options are set/get the same way. Snit can create them, no binary extensions required.

JH: I have not seen significant and/or successful xotcl-based megawidgets, whereas I find building snidgets to be a pleasure in comparison to anything else. I would hope that this TIP would provide something snidget-like that works well with Tk and is fast (snit won't scale as much due to being pure Tcl).

SRIV I have tried Gustav's simple widget creation templates which worked, but couldn't create widgets whose name start with a period. I'd guess that issue could be addressed.

DKF: Once (if?) 257 has gone through, TIP#180[L1 ] would be a good place to take up the cause of a megawidget support class.

DC: I will gladly take up the banner of creating the megawidget framework (TIP #180) in the new OO system if this TIP is implemented. I also plan to convert BWidgets over to this framework as soon as it's complete. This is something I have wanted for a long, long time. Anyone who's ever had to write a BWidget from scratch would agree with me. 0-]

NEM: I have written substantial comments on this TIP today. In the absence of a post on tcl-core yet, I have put my notes up on my website [L2 ].

Artur Trzewik I am quite glad that more are more people are interested in XOTcl.

Some my comments to TIP:

1) I do not like the idea of exported/unexported (public/private) methods. Public API are methods that are documented as public API. There are no advantages to have it supportet in system. By developing code there is not clear if the method are private or public at the beginning. The same thing is with so called ("Internal") methods ("not virtual" in C++) discribed by NEM. Tcl is good for quickly developing why think about (export or inport) , (virtaul or not virtual). I think, that the most often refactoring task in C++, Java or C# are changing of member visibility or virtual nature of methods.

There are also not corresponding hiding functionality in core Tcl. Example "Internal procs, which can be called only from own namespace."

2) moving some methods from Object to special procedures (info, define). It is briliant idea of Smalltalk and XOTcl that all thinks that concern the object belongs to it. It is also important idea of OO (Encapsulation). One can only manipulate an object by using its interface, why have another magic proc that is smarter that object itself.

There are also no reason to devide functionality into runtime and design. There are no such disjunction is core Tcl. Indeed defining procs in Tcl is runtime. There are no special compiling step. I hate this C++ syntax by ITcl that suggest it. Some systems introspects and compute objects and methods on the fly.

3) "Class" should be "class". It means also that all class names in OO code should use lower case. Its break with long tradition of upper case class names (Smalltalk, C++, Java, C#). It is good for reading and understanding.

Object, Class is thing it is upper case. Method is task. It is lower case.

Because Tcl have no special oo function call syntax it is also very good to differnciate: Is it procudural Tcl call or Class method call?

    MyClass classMethod arg1 arg2
    standardProc arg1 arg2

C++ has not such problems because arguments are in parenthesis.


German language use upper case for all nouns and lower for another. It is good thing.

It does not break with core Tcl naming convention. Because OO is new concept in core Tcl. The names in core Tcl are procedures and namespaces. Namespaces are good to differenciate bauses of :: syntax and clear usage. Procedures are "verbs".

NEM wishes all these discussions (here, on comp.lang.tcl, on tcl-core, and on the XOTcl list) were all going to the same place (ideally, either the newsgroup or tcl-core). However, as that isn't the case, I'd like to answer a few points from above:

  1. Exported/hidden method distinction is important for separating interface from implementation. This is especially important when using inheritance, as it is all to easy to clobber some implementation detail in a super-class if there is no attempt to make a distinction. It is also useful for removing clutter from interfaces and making clear which methods are actually important (e.g., in introspection). The mechanism (as I envision it) is merely one to limit scope to prevent accidental interference, rather than an access-control mechanism.
  2. I don't think objects should be the owner of all methods that operate on them. Think of e.g. MVC. Better to split things up into separate interfaces (which can still be specialised on a per-class/per-object basis). This is what define does (although, I think there is a better split that could be performed). Objects should generally provide some basic interface which covers what that object is/does. e.g. a "person" class might provide methods for getting/setting name, address, date-of-birth etc. It might be nice though to provide separate "views" of the same object, where methods from a particular interface were available.
  3. Tcl uses lower-case for everything, according to the style guide. Even "things", for instance string and dict rather than String and Dict. Any oo system integrated into Tcl should be consistent with the rest of Tcl. You are, of course, free to name your own classes with uppercase, and even to rename (or alias) the built-in classes.

Artur Trzewik There are many reasonable features (method visibility, interfaces, strong typization) that are good implemented in another languages. But it is not Tcl way in my opinion. Its strong is small footprint by writing and maintaining code (also understanding) You need much more code to do thinks in J2EE and you need more line changes to provide additional functionality comparing to Tcl. If you use MDA-Tools that works good with such languages it will be not big problem because there are generators that write code for you but I do not expect MDA-Tools for Tcl. Please do not make TCL to police state programming language as C# and others.

NEM Nobody is suggesting any such thing. Turn down the rhetoric. Inheritance as implemented in XOTcl effectively collapses several namespaces into one (from the point of view of methods-calls through my/self), and provides no mechanism for resolving conflicts in such a situation: more recent definitions can silently clobber implementation details of super-classes. IMHO, that completely destroys any modularity benefit that using OO got you in the first place. This isn't about "police states" or enforcing policy, or any other nonsense. It is about making sure that the language behaves sensibly under composition. If you don't want to make a public/private distinction then simply declare all your code public (I would expect that the XOTcl compatibility wrapper over the core OO system would do that anyway). But it is much more difficult to go from a system with no public/private distinction to one which has it. Remember as well that some OO systems which will be expected to be implemented on top of this core OO facility do make a public/private distinction (e.g., Itcl), and so having this facility already present in the core OO saves them work. It would be interesting to see how an Itcl-over-XOTcl handles this issue.

DKF: The newsgroup's still operating in "stunned disbelief" mode at the moment (28-Sep-2005, early morning GMT+DST). :^)

LV seems like discussion on the tct mailing list would be another possible venue...

RLH: If accepted (and I hope it is), when would it be integrated?

SYStems I have a question. We have objects, those objects know things (facts and how to do thing). What we want is an interface to defines, store, retrieve and manipulate this object knowledge.

Why do we stuck oursoulves into storing this type of knowledge into a class hirerachy, why not think relational? the relational model allow one to many and many to many relations data sharing between objects.

Point is, the relational model, can be used as model to interface with data (code is data, class methods are data). I remember I read something for Fabian Pascal saying that the OO model doesn't have an equivilant of the relational model tables. So why not store object knowledge (data and methods) in (relational) tables, why are we stuck with hierearchies?

NEM Why not allow both? This TIP proposes support for OO, and doesn't mandate its use or in some way make it the only possible paradigm available for Tcl. If you want support for the relational model in the core, then you could submit an additional TIP. But that is a separate issue as to whether Tcl should support OO. There is talk surrounding this TIP about what is "Tcl-ish". To me, Tcl is primarily a multi-paradigm language: it provides support for many different styles but mandates no one in particular. This TIP improves support for one paradigm (OO). Further TIPs could improve support for other paradigms, e.g. functional/declarative programming (I can think of a few things I'd like here), or relational etc.

SS 30Sep2005: FWIW, I agree with Artur Trzewik that explicit public/private/... for Tcl is not a good idea at all. The OOP system for Tcl should be designed in order to play well with this (very dynamic) language. Tcl does very little to avoid programmer's stupidity, and in doing this allows the expert programmer to have more freedom, why don't take this principle for the OOP system?

NEM On the contrary, Tcl does do things to prevent programmer stupidity. For instance, making sure that variables in procs are local by default. Perhaps instead of making vague comments about flexibility and freedom you would care to actually address the issues of modularity (accidental clobbering of implementation details) that I raise in my notes, and then also precisely detail how proper encapsulation and allowing (note, allowing, not forcing) hiding of information somehow restrict your freedom or ability to work as a programmer?

SS Hello NEM, I think that proc vars are local by default is a matter of sane default. Avoid programmer stupidity is something like:

  proc foobar {a b c::readonly} {

or some other kind of restriction in the ability to operate with data/functions in a way you like. When in a language there is something like uplevel and upvar I think it's very hard to support the idea that this language try to protect from misuse. About the OO system, in order to be less vague, I think that what it's needed is something of radically simple as idea, for example "all methods public, all variables private". Not by default, but just it works this way, this is how SmallTalk works. Note I'm not proposing exactly this design, but it is an example about how an OO system for Tcl should be conceived in my opinion: simple to learn, simple to describe, yet powerful, like smalltalk. The rest is a matter of tastes, I may like a way to do things, you may like another one, so there is little to argue, instead what seems an idea that can be shared across different designers is that if a language is in a give way (few orthogonal concepts), the OO system should follow this guidelines. A side effect of a

NEM I think making implementation details private (not inherited) is also a sane default. Furthermore, it is the only default that actually gives you a choice. If you allow a public/private distinction to be made, then the programmer can control whether to use it or not. If you don't have any such system, then the programmer must implement their own ad-hoc solution over the top if they want to use such a facility. Rather than giving the programmer more flexibility, I'd say that this search for freedom actually hobbles programmers who would make use of such a facility. And again, it is expected that OO systems like ITcl which explicitly have such a facility will be easily implemented on top of any core OO system, so it really makes sense to have the facility there for those who want to use it. Public methods/private variables doesn't address the concerns I raise in my notes (which were solely to do with methods). The problem is that if Class B inherits from Class A, then without a public/private distinction all of A's methods are visible (and overrideable) in B. This leads to a fragile system, where the author of Class B has to know a lot about the implementation details of A in order to not accidentally break its functionality. Further, any subsequent changes to Class A's implementation may introduce incompatibilities with any number of subclasses. To me, it is the potential for subtle bugs that this introduces which would be a real barrier to simplicity of learning and use. Being able to specify interface separate from implementation details (whether by public/private or export lists or whatever) is an essential part of an OO system which allows inheritance. Again, if you are going to make statements that the proposed system is going to be difficult to learn, or is overly complex, or badly designed, then you need to actually detail your concerns. I very much agree with you that the TIP could be simplified, and that the final system should consist of a minimal set of orthogonal concepts that provide the maximum coverage of functionality. I think the proposed system is not far away from that, and it being revised towards that goal, so I'm still a little confused as to what exactly (beyond public/private) you feel are the overly complex features in the TIP.

SS: In short, no filters (nor other access control capabilities), no mixins, no metaclasses, MI is good if the semantic is trivial, ability to intercept the dispatching process directly if one really wants to perform radical changes. Also IMHO instproc is not a good word at all but this are just minor issues. That's all. P.S. It's cool that this is happening (OO in Tcl), thanks to the people that are making efforts about this.

escargo 29 Sep 2005 - I was surprised to discover that there was a new standard for Fortran (Fortran 2003), and that it included object orientation. One site offerred this remark[L3 ]:

"The object-oriented features are based on type extension, polymorphic variables, and type-bound-procedures. This fits the pre-existing Fortran language better than the more usual class-oriented model, while still providing inheritance and object methods (dynamic dispatch) in the expected manner."

Not that I am trying to imply that what Fortran does should guide us, but it might inform us.

NEM In what way?

escargo - Fortran 2003 is an example of adding OO to a language that did not previously have it. (Athough I would not be surprised if there weren't bright people who came up with preprocessors to extend the previous version of Fortran to add some OO to what they could then write.) Rather than making the radical jump to adding Class/Object OO, they are trying to achieve (what they perceive to be) the benefits of OO by other means: extension, polymorphism, and dynamic dispatch. Since Tcl's notion of type is much different than Fortran (because everything is a string), polymorphism is somewhat easier, but dynamic dispatch would not seem to be automatic. (One might see it as related to delegation.)

I suppose there are two questions that are fundamental: Why add OO to Tcl? and What is the best kind of OO to add to Tcl? (That last question assumes that the number of kinds of OO that can be added can be enumerated and compared, which might be comparable to the halting problem [L4 ].) Maybe there are three questions: What is the problem, what are the solutions, what is the best solution?

NEM I think we should be beyond "Why add OO to Tcl" debates now. We've been having them for years. A more pressing question now would be "Why not?". I really don't see adding an object system as being a "radical jump" after a decade or so of it being requested, and even longer of OO being the dominant paradigm in industry. I see the current proposal as being more like adding CLOS to Common Lisp. You can still ignore it if you want to, and the core Lisp still remains the same. But it's there and it's standard for those who want it. Nothing about the proposal precludes future addition of other features, or support for other paradigms.

I'm slightly confused by your discussion. I suspect that the space of possible OO systems forms a spectrum rather than a continuum, and could be enumerated. This would involve breaking down the cluster concept of OO into a set of individual features present in a variety of popular systems that are referred to as OO (such as ad-hoc polymorphism/overloading, dynamic dispatch, inheritance and other extension mechanisms). Such a survey and a review of the literature (e.g., [L5 ]) might well be useful, and would probably enhance the rationale of the TIP. However, I think it would most likely conclude that the proposed set of features (based on XOTcl) would indeed address a good chunk of this design space, which is probably sufficient. Do you have evidence to the contrary?

escargo - As usual, I'm not as clear expressing myself as I think I am. Expanding slightly on my last series:

  • What problems in developing Tcl programs is OO expected to solve?
  • What are the solutions (or components of the solutions)?
  • What methods do you use to measure how good a proposed solution is?

I'm confused by the distinction you draw between continuum and spectrum. Would you accept range instead? (I'm not trying to imply anything about quantization.)

If there is a major difference between some of the possible OO implementations, it might be between Object/Class OO and Prototype-based OO[L6 ]. To me (and maybe me alone, apparently), prototype-based seems like a natural fit with Tcl. I guess I imagine each object has being an array that holds its instance variables (with each name as the key) and methods (with the method name as the key). (That array would the equivalent of the slots used in some of the prototype-based object languages.) There are certainly other possible mechanisms as well, but that's what I imagine would underpin such an object system in Tcl.

NEM I suggest that those are the wrong questions. OO as a methodology shouldn't have to justify its merits in the context of this TIP. It should be sufficient that it is an established methodology which many people would like to make use of. Again, let me pose the opposite question: what problem do you envision to arise from adding OO to the core? So far, I have yet to see one coherent argument against adding OO. There are arguments against making Tcl OO through-and-through, but that is not proposed and so is irrelevant. There are also arguments against the particular set of features proposed in the TIP. Some of those concerns are valid and deserve attention, but they are details. There is also an argument against introducing "bloat". However, as others have pointed out, 8.5 is already likely to be somewhat larger than 8.4, due to clock enhancements, libtommath stuff etc. Additional size is therefore not on its own a reason to reject the TIP, as that would effectively rule out any further feature enhancements for the same reason.

A spectrum is made up of discrete bands. A continuum is a continuous range.

Lars H: Not true, lots of things have continuous spectrums. The most elementary physics examples are free particles.

(NEM: I wouldn't call them spectrums then, but clearly we differ on terminology. No matter, it is completely irrelevant to the discussion at hand. The point I was trying to make is that the design space of OO systems is, IMO, both countable and finite. I offer no proof of this, as the term "Object Oriented" is in practice not well-defined.)

NEM (continued): The former can be enumerated, as I suspect is the case for OO systems: while there are a lot of concepts associated with the term "OO", there is a finite number of possible combinations of such concepts. But still, none of this has anything much to do with the Halting Problem.

If you would prefer a prototype-based OO system to the XOTcl system proposed, could you please identify ways in which the system described in the TIP cannot implement a prototype-based system? (I think it can, quite easily.)

escargo I am not against add OO to the core. I'm not against adding changes to the core that enable OO (especially different kinds of OO). I'm not trying to hold Tcl back. I was mightily impressed by the names of the authors of the subject TIP. If the additions to the core enable OO without degrading the rest of the core, then, by all means, let's go forward. Perhaps it would improve the performance of Snit, which I happily use. Sarnold : perhaps something like itins or xoins (snit-like emulation in ITcl and XOTcl) would give you the expected speed, although it would not give you all the functionalities...

RLH: I am hoping that it will improve the speed of Snit, as I really like that model of OO.

(Perhaps an alternative formulation of the halting problem might convey my meaning better: For any proposed change in Tcl, can you predict when people will halt debating it and do something?)

PWQ 29 Sept 05, In response to NEM's comments above. What I find most interesting is your statement that OO is of merit in its own right so the rest of the debate is moot. It can be seen that database access is also of merit in its own right, however we will not be seeing the TCT pushing through a TIP for a database access infrastructure placed into the core so that developers don't have to reinvent the database wheel.

Another failing of this TIP is that it falls down on its raison d'etre. Its purpose is to allow OO without having to reinvent the wheel, when in fact what is proposed is placing a specific type of OO into the core; in fact I would go further and say that the proposal is to place XOTcl into the core. Any OO methodologies that are not class-based are back to the drawing board.

DKF 30-Sep-2005: While database access might be of value (it's not for my apps, but that's an unrelated matter) there are a few reasons why there is no database access stuff in the core. The most important two are:

  • We can't in general distribute the database access libraries themselves (due to all sorts of variants on the theme of "licensing") so building the core with them would be tricky at best.
  • Nobody's done a concrete proposal of what to do!

On the matter of OO/XOTcl, it is a fact that the large majority of OO systems that people will have had exposure to are class-based in one way or another. Furthermore, XOTcl has sufficient advanced primitives to support modes of operation that look like the other major Tcl OO systems that it is reasonable to hypothesize implementing those other ones on top of it. By contrast, it's probably not practical to even consider building XOTcl on top of [incr Tcl] or Snit.

Given that we need some OO in the core (and that argument has actually been won for quite a few years now - we get beaten up on it as a language in all the "objective comparison studies" done by outsiders, and it really does make a difference for larger programs where you end up having to do some kind of OO to make them tractable - together these mean we have a strategic need for OO, and I firmly believe that one of the duties of the TCT is to act for the strategic health of the language and community) the first implementation has to support class-based OO. Prototype-based OO is just much further down the agenda.

Of course, the intention is for the core OO system to offer something to anyone doing OO. I think the key things are probably high-speed method dispatch, data encapsulation and dynamic modifiability. Everything else is nice, but those three are the real heart of it. Given those, I think you can actually build quite a neat prototype-based OO system with just a little cunning. :^)

The other point is that we do not need to get this perfect straight off. We can afford to evolve toward a better solution.

PWQ, I would have to agree with DKF, OO is all about marketing. NEM claims that having OO as part of the core will not affect those of us that have no interest in OO. Looking at the comments in here it is clear that the first thing that will happen is that all the existing Tcl library code will be converted over to use the OO system. Kind of ironic don't you think, when this TIP is designed to stop people reinventing the wheel.

NEM What makes you think that all existing library code will be converted over to the new system? Individual authors may convert their code, because they perceive an advantage to doing so. In addition to DKF's comments above, I'd add that, although XOTcl is class-based, classes in XOTcl are just another type of object. People who are commenting that the proposed TIP imposes a particular, inflexible form of OO seem to me to have neither read the TIP, nor examined XOTcl in any depth.

jima I agree with NEM, XOTcl, as it is said in its own documentation, is more object- than class-based. Item more, I also agree with the perception that it has enough primitives to implement many of the particular OO desires of individual coders. As for the Database business, it also falls into the category of good marketing features a modern language library should have. Some (XOTcl'ed) ideas on a common object wrapper for this might be found in Artur Trzewik's XOSql.

SS: jima writes I also agree with the perception that it has enough primitives to implement many of the particular OO desires of individual coders, warning: probably it's true the reverse. In Tcl we have a lot of freedom at the point that's nearly possible to reimplement everything in Tcl itself because Tcl offers very little primitives, but very good and general ones. Languages with more primivies like Python are less able to adapt to the coder. I think it's the same for the OOP, so it is a matter of selecting few powerful dynamic features of the OOP system, not to overload it to make everybody happy (ending with a bad design).

jima: Perhaps I should have not used the terms primitives here. I am aware of the power of Tcl to reinvent (tcl is more based on rules than in primitives, that is for certain). The point is to state that XOTcl restricts in very little if anything at all that power when dealing with code structured following OO paradigm. I think Snit's delegation, Traits, Itcl, and many more things can be implemented all following the model (perhaps rules as in the sense I brought the term for plain tcl) proposed by XOTcl (I am eager to see more on TOOT, perhaps I will give it a go). And I don't think it is an overload. On the contrary, the perfomance seems good to me.

NEM Salvatore, if you have specific criticisms of the features detailed in the TIP, then please detail them (preferably as a message to tcl-core). I myself have done this. Blanket vague statements about "bad design" and "freedom" aren't terribly convincing, or terribly helpful.

SS writes, jima: Got your point about "primitives". NEM: I've not specific criticisms about the TIP, I just think it's not the way to go in general. I proposed in the past my ideas about an OOP system multiple times, there is track on this wiki, command based, fixed rules for public/private, simple inheritance with the ability to override methods, ability to change both object's class, and class's details/implementation at runtime. I think that such an OO system can be simple to learn and very effective. I'll not be happy only with a TIP that exactly is the way I proposed the OO system, but I'll continue to think that's a mistake to plug in Tcl an OO system that contains many concepts (that in my opinion are less valuable than the complexity they add).

NEM 2 Oct 2005: OK, I can certainly agree with the sentiment. But could you enumerate the concepts proposed in the TIP which add more complexity than value. (I'll volunteer pre-/post-conditions and invariants, as I think they can be culled without much loss. Indeed, it looks like they have been cut from the latest version of the TIP).

LV Over on comp.lang.tcl today, DKF corrected a misconception I had been deluding myself under. I thought that this tip was proposing a set of functions/procs/capabilities that any object system writer would then be able to use. But I did not realize that it was, in fact, an OO system in and of itself. So what this tip is proposing is that a minimal subset of OO functionality be added to tcl, and that, if it happens to overlap in world view with that of another OO writer, then that OO writer can feel free to make use of the tools. But, if it is in fact its own OO system, then I would expect that a subset of the people clammering for any OO system in the core will turn to this and live with the subset. The subset that will do this are the ones who don't care what the OO system does - they just want one in the core. However, anyone else who wants specific features not provided can at this time continue loading the extension that provides that functionality.

However, one of the main technical arguments (I plan on continuing to ignore political arguments) I hear for including an OO in the core is that having to load an OO extension means that potential incompatibilies are going to occur when extension 1 uses oo system A and extension 2 uses oo system B. Once this TIP is approved and implemented, that argument either continues to be true (because the included functionality isn't sufficient) or is no longer true (perhaps because extension writers give up on using the software they prefer, in favor of what is already on the system, even if it means providing less functionality).

The first decision branch means that oo hasn't really provided any improvement. The second branch would, by some at least, be considered a bad thing if the result is lesss functionality.

I'm still not convinced that any OO needs included. But if something is going to be included, either using one of the full OO functionality, or ensuring that whatever is included provides enough functionality that no OO extension is going to be hamstrung if they make use of it, seems to be the best choices from my viewpoint.

MR Larry, we're long past that point. The TCT, taking into account both technical and what you would term political reasons, is clearly aiming to move forward with this, finally.

Of course, anyone who thinks these things moving forward is such a bad thing is always free to make their own version of Tcl and see how well that goes over. I'd suggest naming it "Tcl Pure and Unadulterated" or "Tcl/P.U." for short. ;-)

PWQ 1 Oct 05, No other addition to TCL has been deemed necessart to include in the core. So I think that it is fair for others to question the motives of the TCT when XOTcl / itcl have existed as extensions for years. I don't see anything to suggest that anyone will have to package require oo for it to be available.

In response to NEM somments about rewriting code. I suggest you read this page and the chatter on tkchat, for clear examples of developers chomping at the bit to do exactly that. First it will start with tklib, and then bits of tcllib will be hacked. Like a virus it will spread until every programmer that wants to use tcllib et al will have to do so via the OO interface.

Argue until you are blue in the face if you want. But the intense pressure of OO programers that has forced the TCT to make OO a core addition will not sate their appetite. I critise OO developers on their results , OO developers critise based on idealogical views.

When the dust has settled, Tcl will not be better for it , just slower and fatter.

CMcC (051003) It is clear, PWQ's personal preferences notwithstanding, that there is a need for OO. That's why it's been re-implemented several times in mutually incompatible ways to support various components of tcllib. If there were a single OO framework in the core, there would be a strong incentive for programmers to use one of a smaller number of less idiosyncratic OO systems.

Far from tcllib being hacked, it would be possible to substantially improve its implementation. Hopefully it will spread less like a virus and more like an idea whose time has (finally) come.

PWQ seems to miss the point that tcllib is already substantially implemented with OO techniques, and among the very programmers he criticises are programmers whose results he seems to value. I strongly hope that this tip will not sate their appetite, since their appetite to produce (for example) tcllib code benefits all users of tcl.

schlenk {051003} I can just agree with Colin here, tcllib would benefit from OO in the core, slowly (due to compatibility reasons, many packages try to support Tcl 8.2), but noteworthy. One thing that could happen is increasing number of dependecies for individual packages, but thats a natural thing. There is no real point in having for example a struct::list package but inlining most of the code instead of a single package require just for the sake of reduced dependecies. Its a similar case with OO. Currently lots of different incompatible partial OO systems are littered into the tcllib packages, be it struct, logger, etc. etc. Those could be consolidated into a fast core oo system.

DKF: Just noting that I've been trying to pare down #257 to just about the bare minimum. Extravagances left in are two extra support classes (to be used or ignored as people see fit!) and filters and mixins ('cos they enable cool stuff). Hopefully, that'll leave plenty of room for other people to produce full OO systems (with class libraries, lifetime management, etc.) on top.

Twylite (2006/04/13) Do we need OO support in the core? Yes. The many reasons include that the community obviously wants to have OO available (witness the number of extensions) and without core support the extensions may not be available on your platform / distribution or may be unacceptably slow.

That said, there is a huge difference between OO _support_ in the core, and the XOTcl-like core functionality proposed by TIP#257.

The purpose of OO support, and the stated purpose of TIP#257, is to allow OO systems to be built on top of that support. Of course TIP#257 will also provide a fully functional OO system in its own right, in order to meet the requirement that code can use a decent OO system without having to rely on an extension being present. This is a Good Thing IMHO.

My concerns with TIP#257 are that (1) it tries to offer too much, (2) it doesn't "feel" like Tcl, and (3) it pushes out the availability of 8.5.

I feel that is it essential to develop a _simple_ system now, and add more functionality later if it is required -- you can always add on later, but you can't take out what you put in now!

(1) A huge part of Tcl's value (IMHO) comes from being easy to learn, which makes it important to strive for simplicity and consistency in the core (yes, I know this doesn't always happen). I really don't think that filters or forwarders/delegation belong in this TIP. Sure, they are useful -- especially in the context of objects -- but they're not specific functionality of an object system or essential for basic OO support.

Filters need to be part of a separate TIP that will consider their applicability to classes, objects, namespaces and globally. Forwarders would also have value globally, as a more powerful and more intuitive alternative to "interp alias", and a mechanism to implement aspects efficiently.

(2) Let me illustrate what I mean by "it doesn't feel like Tcl". Imagine defining a namespace proc like this:

  namespace myns proc myproc {args} {body}

That's pretty much what TIP#257 is suggesting:

  oo::define myclass method myname {args} {body}

I believe that the majority of Tcl developers see OO as a logical extension to the namespace mechanism. I would expect a purely static class not just to look like a namespace, but to _be_ a namespace. I would also expect member visibility and class resolution to use the same mechanisms as namespaces: namespace export and namespace path. Something like this "feels" right to me:

  namespace eval myclass {

    # class variable
    variable x       

    # member/instance variables
    instvariable y
    instvariable -publicy

    # superclasses ; we could use "inherit" as syntactic spice for 
    #   "namespace path".
    namespace path classA classB

    # class method
    proc classProcA {args} {body}

    # instance method
    method instMethodA {args} {body}
    method _privInstMethodB {args} {body}

    # constructor
    constructor {args} {body}

    # destructor
    destructor {body}

    # declare public/visible methods, as for "namespace ensemble"
    namespace export classProcA instMethodA configure cget

    # Here's some cross-cutting functionality using syntax from TIP#TBD
    forward cget ::oo::cget 
    forward configure ::oo::configure
    forward log ::mylog::do_log -src myclass
      # args to log are tacked on after "-src myclass", as with 
      # "interp alias"


All procs, methods, and the constructor/destructor could be declared outside the "namespace eval" using qualified names:

  method myclass::instMethodB {args} {body}

Next, class and instance variables must be explicitly pulled into a proc/method, using "variable" and "instvariable". This is consistent with the rest of Tcl, and is a Damn Good Thing because it makes it a whole lot easier to analyse procs and methods for invalid references. The assumption that all variable references are local unless qualified is fundamental to Tcl, and shouldn't be violated.

  method myclass:instMethodB {args} {
    variable x
    instvariable y

    # This will throw an error because -publicy isn't in scope
    puts ${-publicy}

I would expect to create objects using something like this (*):

  set inst [myclass new]  ;# auto naming
  set inst [myclass new instname]

and call them like this:

  $inst methodname arg arg ...
  myclass procname arg arg ...

and destroy them like this:

  destroy $inst

Within an instance I should be able to call an instance method without qualification or using "self" or "$self", in the same way as namespace procs can call each other. I know this is technically less than simple ;(

(*) This is different to Tk widget instantiation, but Tk widget classes (a) don't have class methods and (b) require a name. If you allow "myclass instname" to create an object then you end up with objects floating around whenever you call a class method that doesn't exist. Ick!

A namespace can be assumed to represent a class if any of { method instavariable constructor } are defined. Default methods that are typically available to all instances, like "info" and "eval", can be added to objects automatically.

I am aware that I have not addressed all aspects of an OO system here -- these are just the basics that I feel TIP#257 isn't getting right. The rest of an OO system flows around these basics.

(3) I'd also like to make the point that the world is waiting for Tcl 8.5 and its numerous enhancements.

It seems to me that proposals like OO and Tile need to be more mature, and left for an 8.6 release.

This also makes sense considering the wealth of 8.5 functionality that has already been implemented (or is planned) and benefits or is meant to benefit OO extensions:

  • TIP#103 {expand}
  • TIP#112 ensembles
  • TIP#181 namespace unknown
  • TIP#229 scripted resolution in namespaces
  • TIP#250 access to namespace variables
  • leading word expansion

Let's give the Tcl community an opportunity to work these enhancements into OO systems, and see what evolves, what is still missing, and what is appropriate to become core functionality for 8.6.

NEM Everyone has a different idea of what OO in Tcl should look like. The reason for going with XOTcl, from what I understood, was that (a) it is a model that people already use (and so is familiar to at least some people), and (b) it is particularly flexible, allowing other forms of OO to be built on top of it.

With regards to your specific suggestions:

(1) I think you are probably right that the TIP proposes too much functionality in one go. Forwarders and filters would be useful for implementing frameworks like Snit though, and that is one of the intentions of the TIP, AIUI.

(2) I'm also not a fan of oo::define. Personally, I like the idea of sending messages to objects to create methods, e.g.:

 myobj method foo {...} { ... }


 myclass instance method foo {...} { ... }

along with a method for sending lots of messages at once:

 myobj eval {
     method foo ...
     method bar ...
     variable ...

which could also be used by [myobj new] etc. The "instance" method on classes is maybe too verbose, but it appeals to me (after all, you can always layer some shorter alias over it).

Regarding classes being namespaces: this strikes me as thinking too much in terms of implementation details. Sure, objects/classes may be namespaces, but I'm not sure that namespaces are a particular good interface for an OO system. In particular, I think most people want to use the word "class" when creating a class, and not "namespace eval". Likewise, inheritance should be performed by an "inherit" method rather than "namespace path", "public" (or whatever) rather than "namespace export":

 myobj public {
     method foo ...
     method bar ...

I hope I never have to use "::" syntax again, but that's probably wishful thinking.

Regarding having to import all instance variables before use: I think you will find resistance to this idea, although I tend to agree. I personally prefer qualifying all access to member variables/methods via a call to "self":

 self set foo "Hello, World!"
 puts "foo = [self set foo]"

Although, I'd really like to make instance variables themselves be methods/objects:

 self foo := "Hello, World!"
 self foo trace read ...
 puts "foo = [self foo]"

My own preferences for object creation/destruction would be:

 object create foo ... ;# named
 object new ... ;# auto-generate name
 object destroy ;# destruction is another method

Although, I could live with [destroy $obj].

GN Sept 28, 2006 this is exactly like in xotcl. Concerning "::" syntax. Are you aware of the following notation in XOTcl, where one can use an object + procs/forwarders to define subcommands. This works as well over multiple levels, where one can define extensible subsubcommands etc. and use introspection to query the available ones....

  # define some command with some subcommands. subcommands
  # are extensible, one can add at arbitrary times more subcommands...
  Object somecommand
  somecommand proc sub1 {} {return [self]/[self proc]}
  somecommand proc sub2 {} {return [self]/[self proc]}
  somecommand proc sub3 {} {return [self]/[self proc]}

  puts [somecommand sub1]
  puts [somecommand sub2]

  # subcommands can contain other subcommands.
  # Also the sub-subcommands are extensible in the same way
  Object somecommand -contains {Object sub4}
  somecommand sub4 proc a {} {return [self]/[self proc]}
  somecommand sub4 proc b {} {return [self]/[self proc]}

  puts [somecommand sub4 a]
  puts [somecommand sub4 b]

NEM continues ...

But now I've just proposed yet another take on how an OO system should look. What strikes me from looking at these comments (both yours, and my responses), is that they are almost all down to matters of syntax and how using OO should look. While this is important, and something I think we should spend some time on in refining 257, I think we should try to get the semantics right first. I think TIP 257 gets a lot of this right (classes are objects etc), but there are some open questions (which I've already descibed elsewhere [L7 ]).

(3) I think you are probably right here. 8.5 should probably be released soonish, and leave Tile and OO for an 8.6 release (or the mythical 9.0). I don't think we need to develop yet more OO systems though; 257 just needs more time to really think through.

WHD: The purpose of oo::define is to rectify one of the serious problems with XOTcl--i.e., that you can't create an object without half-a-million methods already defined. If you're using an OO library to create a package for public consumption, you want to be able to define clean well-documented interfaces, and you want to be able to choose whatever method names you like without worrying about conflicting with those provided by the OO package. I'm not a fan of C++, or its draconian restrictions on limiting access to object internals; that's not the Tcl way. At the same time, providing direct access to an object's instance variables to all clients strikes me as dangerous.

GN ''28 Sep 06': i just stumbled over this page. There are many things, that should be commented, and i have already in some (partly unanswered) emails to the developer group. Just commenting on this argument: several oo languages provide common behavior only through inheritance from a common base class (e.g. smalltalk, java, ....., xotcl). To stick to the OO paradigm, one defines create,set, etc. as methods that can be redefined. There is no way to e.g. create and object/class/method without a method allowing this. Therefore, classes like ::xotcl::Object has these methods, all these methods can be shadowed, refined, etc. However, since the last few releases, xotcl has a light weight means to attach from the tcl level (c-implemented) methods to objects/classes. Since the last few releases, the xotcl c code creates ::xotcl::Class and ::xotcl::Object completely without behavior, all methods are attached from the script code initializing xotcl. This was implemented to share behavior without the need of inheritance or forwarding.

NEM 21 Aug 06: XOTcl does provide rather a lot of methods on objects by default [L8 ]. However, I think this points to a general problem, in that a single object may support multiple interfaces and could have lots of different methods (some of them conflicting). Rather than giving up on this problem and moving these object creation/life-cycle methods out into oo::define, perhaps it would be useful to come up with a solution to this problem? Perhaps ensemble methods would help?

I'm not sure where the comment about "providing direct access to an object's instance variables to all clients" comes from. It's been a while since I last read this discussion, but I don't believe anyone suggested that.

DKF 22 Aug 2006: The actual plan is to break the functionality up so that:

  • if you want just the bare bones, you can get it using oo::object,
  • if you want to have somewhat XOTcl-style variable handling, you use oo::struct,
  • if you want to have somewhat XOTcl-style definition methods, you use oo::definer, and
  • if you want both, you use MI to get both.

Also note that things get easier to use using the following little incantation in your current namespace:

 namespace path oo

DGP Given that incantation, I'd repeat a gentle request to create these new Tcl commands as tcl::oo::object, etc. and encourage the incantation:

  namespace path tcl::oo

DKF: This (the naming of things) is one of the parts that is utterly negotiable when we come to review the TIP later on. Until there's more implementation in place, I'm not going to bother doing this for now. :-)

Sarnold started a discussion, which is now at Basique - OO-like namespaces.

SG 20 Aug 2006: Does Tip #257 include whatever extensions are needed to the public C api so that objects can be defined from C?

DKF: It will to eventually, but since I don't know what the C API needs to be yet it's hard to say what it's going to look like. Right now, I'm planning at least to have functions to create new objects (and hence new classes), to lookup objects by name/Tcl_Obj, and to install new methods. Well, when I say "planning" I mean that I have prototype versions of the code. :-)

SG 29 Aug 2006: Is there a well-defined way to get the destructors to run prior to interpreter cleanup? XOTcl has the setExitHandler mechanism, but I've found that it's not really well-defined in the presence of threads. Or do you have to overload exit?

DKF: There is no mechanism for doing that. By the time my code detects that the interpreter is going away, it's usually too late to run destructors; the interp is already in the "doomed" state and Tcl_InterpDeleted() is returning true. Maybe it'll be possible to add something to fix this, but I'll leave that well alone for now. (FWIW, there's no way to intercept all ways an interpreter can die; if you tie significant resources to an object lifetime, you can leak.)

SG 29 Aug 2006: How does this interact with threads? My guess is "not at all", but it would be nice if there was a way to transfer objects between threads, similiar to the way channels can be moved.

DKF: The code is thread-oblivious because objects are utterly interpreter-specific (and have to be, since they're several commands and a namespace, none of which can be transferred between interpreters in classic Tcl code).

SG 29 Aug 2006: Is there a "move" operation, in addition to a clone? XOTcl implements "move" as a deep copy followed by a destruction of the original object, but that can be expensive and a bit of pain. (I once tried to implement a resource pool of static objects where the constructor "move"'d the objects out of the pool and have the destructor "move"'d them back, but XOTcl's deep copy & destruction made it tough.)

DKF: 30 Aug 2006: There is no "move" operation. Use rename.

SG 31 Aug 2006: But aren't objects (at least paritally) also namespaces? If you rename the object command, what happens with the associated namespace? Does it follow along for the ride? Or will somethings fail if the object command is renamed?

DKF: The command name has nothing to do with the namespace name (except for being initially coincident if you use the new method) and nothing in the object implementation depends on the name of any particular object. Objects have, at the C level, a deeper reality than their names.

SG 1 Sep 2006: Ah... So the command name is just an opaque handle? In that case, why not make the namespace distinct so there's no possibility of someone accidentally (mis)using the object by accessing directly through the namespace? In fact, can the namespace be "anonymous" (like a file handle, or the like)? Somebody could always do a namespace current, but it might be nice if there was no obvious relationship between the command name and the object name.

DKF: It's always easier to create one unique thing than two. :-) Moreover, if you create a named object (and all classes are named objects) then it will always be distinct from the namespace. You will be able to introspect the object to get the namespace though. Everything is "open if you know where to look". :-)

APW: I have just looked at the available version of oo and had some thoughts on how to implement Itcl in a Tcl only version on top of that. I think it is possible to write Tcl code to convert the Itcl class and other commands using the oo:: functionality. One problem I see is to add a Tcl written command and variable resolver so that it will be called from the Tcl resolver functions (written in C). The current implementation of Itcl is using C-level functions. Is there some Tcl level interface or is there another solution for that?