I was in the process of writing this email to ask whether XOTcl currently supports, or could easily be extended to support, a particular pattern of parameter defaults that I often use, and then was pleased to discover that XOTcl already provides most of what I was looking for. Though, it's not documented as such, so I'm not certain whether this was intentional. I suspect it may have been a side effect of the generality of parameters. I don't mean to dismiss the foresight of the XOTcl authors, but since it is a simple mechanism, and not documented, I am concerned that the feature may disappear in the future.
The pattern is simple - parameter defaults, instead of being constants, should be changeable so that client code can modify the defaults as desired. For example, if the default is a class variable, then client code can modify the class variable. Then, when a new instance is created, the new default is used. To extend the example from the tutorial:
Car set doors 8 Car create limo limo doors ; # ==> 8 Car set doors 5 Car create minivan minivan doors ; # ==> 5
I originally supported this pattern by putting the appropriate intelligence in the init instproc. But, since I use this pattern a lot, I saw that code commonly in many of my init instprocs. So, I was looking to find a way to have XOTcl automatically pick up the default from the class. I decided that the most general thing to do was to put a script in the default and then execute it. But, when I tried that, I found that XOTcl executed the script for me! So, to support the above, I simply did:
Class create Car -parameter { {doors {[[self class] set doors]}} }
I also found that the default can be a simple variable, though accessing it requires scope qualifiers (but, I find this much less useful):
Class create Car -parameter { {doors $::DOORS} } set DOORS 4 Car create sedan sedan doors ; # ==> 4
Obviously, XOTcl supports much more general default behavior than I was originally looking for. But, for me, this is the appropriate solution. I can express simple defaults very simply. If I am looking for something more complicated, I can create a proc to support it, and then have the proc called.
Note that with parametercmd we can make this slightly cleaner to use:
Class create Car -parameter { {doors {[[self class] doors]}} } Car parametercmd doors
Car doors 8 Car create limo limo doors ; # ==> 8 Car doors 5 Car create minivan minivan doors ; # ==> 5
This then begs for automatic creation of the parametercmd on the class. I had hoped that this could be accomplished by subclassing Class::Parameter and extending the init instproc (note that I had to actually use ::xotcl::Class::Parameter), but this did not work:
Class MyParameter -superclass ::xotcl::Class::Parameter MyParameter instproc init args { ## I would like to create parametercmd's on the class here; but, I need a handle ## to the class. Is it one of the args? Let's find out: puts [info level 0] next } Class create Car -parameterclass MyParameter -parameter { {color green} } ## Hmm - didn't see what I hoped I would see. Car create ferrari ## init ::ferrari ## ::ferrari ## Ok, this is where the parameter gets instantiated. So, how do the instparametercmd's get created?
Maybe there is no hook for me to do what I'm trying to do? Maybe I just have to accept manually adding the parametercmd to the class? It's not such a big deal, but I thought it might be useful.
Thanks, Kurt Stoll
Kurt Stoll schrieb:
Note that with parametercmd we can make this slightly cleaner to use:
Class create Car -parameter { {doors {[[self class] doors]}} } Car parametercmd doors
Car doors 8 Car create limo limo doors ; # ==> 8 Car doors 5 Car create minivan minivan doors ; # ==> 5
In order to get this still better working, i would recommend to create a metaclass called Vehicle, which sets for every instance class the default number of doors and provides as well the "parametercmd".
Class Vehicle -parameter {{doors 4}} -superclass Class
Vehicle create Car -parameter { {doors {[[self class] doors]}} }
Car create sedan puts [sedan doors] ; # ==> 4
Car create limo -doors 8 puts [limo doors] ; # ==> 8
Car create minivan -doors 5 puts [minivan doors] ; # ==> 5
you can do as well
Car doors 20 Car create choo-choo-train puts [choo-choo-train doors] ; # ==> 20
but i am not whether you will really want this...
I have developed a major overhaul of "parameter" and friends, it will be certainly feature compatible at this level.
Currently one can only specify a value or a command to be invoced at instantiation time of the object (as in the example above). In general there are several situations where the command should be executed e.g. the first time the variable is accessed or on each access of the variable. This is e.g. important, when only a few instance variables are used during lifetime of an object, and the the instantiation command is rather expensive (e.g. a database query), or when one wants live updates on the instance variables...
The new parameter replacement (called slots) is very flexible and much more powerful, in many situations, it will be faster as well. It is as well possible to use the same idioms for mixins/filters (... add, delete) as well for other object/class relationsshipts (e.g. class, superclass) and for user-values as well. Stay tuned. Currently, i am still unsure whether to use and extend the old interface (based on "parameter"), or to use for the more powerful cases the new interface. i have still a lot of integration and testing in front of me. My intention is certainly to keep the suff described above compatible, even with the new implementation.
-gustaf neumann