Hello,
Is it possible to change the -setter command associated with a parameter at some point other than class definition? I want to trigger some side effects from a parameter set operation, but I can't trigger the side effects until after other things have been initialized, so I want to use the default setter method until the end of init, and then replace the setter method (but not the getter method).
I can override create a parameter-named method at init time, but that overrides the getter along with the setter. I'd rather not have to handle the -getter from my proc (the default -getter is fine and 2.5x faster). I've looked through the docs and the tutorial and I can get tantalizingly close (parametercmd), but is there an easy way from within a proc to change the -setter properties of a parameter?
Something like this:
Class create a -parameter {{foo 1}} a instproc foosetter {var val} { # Do something with [self] that isn't valid pre-init } a instproc init {} { #override foo's -setter parameter cmd my parametercmd foo -setter foosetter }
a create b -foo 234 ;# calls default foo setter b foo ;# calls default foo getter b foo 123 ;# calls overridden foosetter
Thanks for your help. XOTcl is a great. It should be adopted as Tcl's standard OO package.
Scott
Notice The information in this message is confidential and may be legally privileged. It is intended solely for the addressee. Access to this message by anyone else is unauthorized. If you are not the intended recipient, any disclosure, copying or distribution of the message, or any action taken by you in reliance on it, is prohibited and may be unlawful. If you have received this message in error, please delete it and contact the sender immediately. Thank you.
Scott Gargash schrieb:
Hello,
Is it possible to change the -setter command associated with a parameter at some point other than class definition?
one can use the method "parameter" at any time to add/redefine parameters (see below).
I want to trigger some side effects from a parameter set operation, but I can't trigger the side effects until after other things have been initialized, so I want to use the default setter method until the end of init, and then replace the setter method (but not the getter method).
technically speaking, if one would like to use a single name for a setter and getter (such as set r [a1 foo]; a1 foo 123) there has to be a single method named "foo", handling both cases. this is not more than a conveniance, one can define an kind of methods that behave as accessor functions.
I can override create a parameter-named method at init time, but that overrides the getter along with the setter. I'd rather not have to handle the -getter from my proc (the default -getter is fine and 2.5x faster). I've looked through the docs and the tutorial and I can get tantalizingly close (parametercmd), but is there an easy way from within a proc to change the -setter properties of a parameter?
the difference in speed is due to the fact that the default setter/getter method is implemented in C, whereas the tailored functions are in tcl. it is certainly possible to program a tailored getter method in C as well, but i doubt that this is worth the effort.
see below for more variations about your example. Aside from these options, you can use variable traces to trigger side effects from set/get/unset operatons.
-gustaf neumann
########################################
Class create A -parameter {{foo 1}} A instproc foosetter {var val} { # Do something with [self] that isn't valid pre-init puts [self proc] my set $var $val }
A create a1 -foo 234 ;# calls default foo setter # redefine setter for class A A parameter {{foo -setter foosetter -default 1}}
a1 foo ;# calls default foo getter a1 foo 123 ;# calls overridden foosetter puts foo=[a1 foo]
A create a2 a2 proc foo {args} { puts "object specific getter/setter for [self proc] $args" switch [llength $args] { 0 {my set [self proc]} 1 {my set [self proc] [lindex $args 0]} default {error "use [self proc] with 1 or 0 arguments"} } } a2 foo 567 ;# call proc foo as setter puts foo=[a2 foo] ;# call proc foo as getter
Thanks for your time and patience in answering my questions.
Gustaf Neumann neumann@wu-wien.ac.at wrote on 03/15/2006 02:46:58 AM:
Scott Gargash schrieb:
Hello,
Is it possible to change the -setter command associated with a parameter at some point other than class definition?
one can use the method "parameter" at any time to add/redefine parameters (see below).
The issue with using the "parameter" method is that it changes the parameter definition class-wide, which is undesireable. I'd like to change a parameters -setter property on a per-instance basis. The intended class behavior is to use the default setter class wide at construction time, but after an instance is fully constructed, each instance should use an overridden -setter. Ideally the per instance -setter is directed to a instproc class.
Right now I have define the -setter property and have an instproc for the class that does the standard behavior, but then in the constructor I define a "[self] proc" to redefine the implementation of the -setter for that instance.
# This is what I do currently Class create A -parameter {{foo -setter myfoo}} A instproc init {args} { # [self] is valid so revector [my setfoo] to have sideeffects [self] proc myfoo {p v} { my set $p $v #do side-effects } } # no side effects at construction time A instproc myfoo {p v} {my set $p $v}
This works (I get the behavior I desire), but it means I have to 1) define a proc that duplicates the default behavior and 2) construct n identical copies of the implementation for the -setter proc, when really I can get by with the default behavior and one copy of the override behavior shared across all instances, just revectored the setter behavior once it's safe to do so.
# What I'd prefer Class create A -parameter {foo} A instproc init {args} { # [self] is valid, revector [self]'s foo setter from default to the side-effectful variant [self] parametercmd {foo -setter myfoo} } A instproc myfoo {p v} { my set $p $v # do side effects }
Besides being more memory efficient, it seems to more clearly express my intent. As you say, a trace would work, but traces tend to look and feel a bit like magic.
the difference in speed is due to the fact that the default setter/getter method is implemented in C, whereas the tailored functions are in tcl. it is certainly possible to program a tailored getter method in C as well, but i doubt that this is worth the effort.
As you may have inferred from my questions, performance is an issue for my application. I'm hoping to avoid having to drop into C (and XOTcl's native performance gives me hope, especially relative to snit), but I'm prepared to move to C if and when I have to.
I've seen the part of the tutorial about wrapping C-extensions with XOTcl, but is there a reference/tutorial for extending XOTcl in C? How would I go about reimplementing a method in C? Can I just use the vanilla Tcl API or do I need to compile/link against XOTcl also?
One thing that has confused me so far is the "namespace on demand" concept. Where are instance variables stored if not in a namespace?
% Object a ::a % a set foo 123 123 % namespace exists a 0
Where does Object a's foo variable reside?
If I wanted to implement a method as a C function, how does the C function find the value of "[a set foo]" via the Tcl API? I.e., what would I pass as the varname to Tcl_GetVar()? Or do I need XOTcl's C API to look it up? Where do I install my C commands such that they are found automatically by XOTcl's method lookup alogrithm?
Is this sort of info spec'd by XOTcl or is it implementation defined? Is this what "requireNamespace" does? I've read the docs but I haven't really grokked it yet.
Scott
Scott Gargash schrieb:
This works (I get the behavior I desire), but it means I have to 1) define a proc that duplicates the default behavior and 2) construct n identical copies of the implementation for the -setter proc, when really I can get by with the default behavior and one copy of the override behavior shared across all instances, just revectored the setter behavior once it's safe to do so.
there is as well the option to use a mixin or to use namespace import to share the proc.
# What I'd prefer Class create A -parameter {foo} A instproc init {args} { # [self] is valid, revector [self]'s foo setter from default to the side-effectful variant [self] parametercmd {foo -setter myfoo} } A instproc myfoo {p v} { my set $p $v # do side effects }
in general, it is certainly possible to parametercmd/instparametercmd; i am currently working on a general overhaul of parameter etc. based on a more general slot mechanism that generalizes parameters and object/class relations (class, superclass, mixins, ...) with more poweful ways to initialze data, etc. one can use e.g "... superclass add " in the same way than "mixin add", and in the same way as one can do this for ordinary attributes. While i am more interested in a powerful and extensible structure, i am also condidering extending the paramtercmd...
Besides being more memory efficient, it seems to more clearly express my intent. As you say, a trace would work, but traces tend to look and feel a bit like magic.
not so bad:
Class create A -parameter {foo} A instproc myfoo {var sub op} { puts "$var is now [my set $var]" } A instproc init {args} { my trace add variable foo write [list [self] myfoo] }
A a1 -foo 123 puts HU puts [a1 foo 234]
I've seen the part of the tutorial about wrapping C-extensions with XOTcl, but is there a reference/tutorial for extending XOTcl in C? How would I go about reimplementing a method in C? Can I just use the vanilla Tcl API or do I need to compile/link against XOTcl also?
there were some recent postings in this regard. in short: look for e.g. the gdbm integration part of the xotcl distribution, or into critcl.
One thing that has confused me so far is the "namespace on demand" concept. Where are instance variables stored if not in a namespace?
% Object a ::a % a set foo 123 123 % namespace exists a 0
Where does Object a's foo variable reside?
xotcl allocates namespaces on demand. this is a speed and memory issue. in earlier versions, every xotcl object had its own namespace, and was quite heavyweight (around 2001). The namespace allocation on demand lead to a significant improvement in speed and memory, since most objects do not need the namespaces. namespaces are allocated on demand, when an object defines procs or subobjects. When no namespace is allocated, the variables are stored in a private hash-table. You can force xotcl to allocate a namespace for an object by "Object create a -requireNamespace"
If I wanted to implement a method as a C function, how does the C function find the value of "[a set foo]" via the Tcl API? I.e., what would I pass as the varname to Tcl_GetVar()? Or do I need XOTcl's C API to look it up? Where do I install my C commands such that they are found automatically by XOTcl's method lookup alogrithm?
look at the XOTclSetterMethod() in xotcl.c, it is (currenty) quite simple.
hope this helps -gustaf neumann