Dear Victor,
an attribute and an instance variable are two different things with potentially different life-times.
- The attribute provides information about instance variables and their properties (such as e.g. default values, which are used when variables are to be created, or methods to access the variable, etc.). - The instance variables keep the actual value, they can be independently set and unset by standard Tcl commands.
Therefore, changing the default value of an attribute does not change its actual value. The same holds for class-level attributes and object-level attributes.
See e.g. ======================== % Object create o {set :a 1} ::o % o attribute {a oldvalue} ::o::a % o a 1 ========================
However, in some respects the object-level attributes are different from the class level attributes: In contrary to the class-level attributes, the object-level attributes check at definition time of the attribute, if an according instance variable exists. If not, it creates the instance variable with the default value. Probably therefore, you assumed, that the provided value is used to set always the instance variable (maybe influenced by Tcl's "variable" command).
Since the attribute and the instance variable have different life-times, deleting the attribute does the fuzz with the the instance variable. Note that after deleting the attribute, the instance variable still exists (see last command below). ==================================== % Object create o {:attribute {x 1}} ::o::per-object-slot::x init methodname=x ::o % o eval {set :x} 1 % o x 1 % o delete attribute x % o x ::o: unable to dispatch method 'x' while executing "o x" % o eval {set :x} 1 ====================================
Note, that the same holds as well for class-level attributes (changing default values, deleting attributes in class level attributes does not effect the variables in already created instances).
One can certainly argue, that the behavior for object-level and class-level attributes does not have to be the same, and that e.g. the life-time of object-level attributes and instance variables should be stronger tied together (defining a object-level attribute should immediately create/overwrite instance variables, altering the default should change its value, deleting object-level attributes should remove the variables, etc.).
One could define currently mixins that could achieve this strong binding. Note, that the other way round, if we hard-wire the strong binding, it is much more effort to get rid of this strong interaction. Note as well, that per-object attributes are a quite heavy-weight machinery for setting variables. I would certainly not recommend to use per-object attributes each time a variable has to be created, at least not in in performance critical or memory critical situations.
I could see at least 3 scenarios for objects, that require sometimes instance attributes:
a) lightweight: just use tcl-variables, no attributes
Object create o { set :x 1 :public method foo {} {return ${:x}} }
b) middleweight: just tcl-variables + setters/checkers, no attributes
Object create o { set :x 1 ::nsf::method::setter [self] x:integer :public method foo {} {return ${:x}} } % o x 1 % o x a expected integer but got "a" for parameter "x"
c) heavyweight: use attributes
Object create o { set :x 1 :attribute {x:integer,1..n 0} {set :incremental 1} :public method foo {} {return ${:x}} }
% o x 1 % o x add 10 10 1 % o x add 100 100 10 1 % o x 100 10 1 % o x {1 hello 2} invalid value in "1 hello 2": expected integer but got "hello" for parameter "value"
For (b) the middleweight version, we have currently no nice method-based interface. Just in the case of (c) with the incremental interface, slot objects are needed (as well in other cases, where some additional meta-data is needed, such as e.g. persistency data, etc.).
We could do (1) bind the life-time of per-object attributes to the life-time of instance variables (2) create not always slots, when attribute is used, but only when needed.
The case (2) could be tricky for "delete attribute", but at least, for often used per-object attributes this could be a win. What is your primary reason for using "attribute" instead of tcl vars? do you use the incremental setters?
-gustaf neumann
Am 29.06.11 19:52, schrieb Victor Mayevski:
In my code I have objects that need some attributes only sometimes. So, that was my attempt to reduce the code and not have to test for the existence of that attribute but just re-create it. In this case, I ended up just having that attribute permanently in all objects at all times. It is not that I didn't have any other way of doing it, it is just that I thought it would have been an elegant and short way of doing it.
Here is another curious code that could be a bug, at least it doesn't seem to behave as expected:
% Object create o ::o % o attribute {a oldvalue} ::o::a % o a oldvalue % o delete attribute a % o a ::o: unable to dispatch method 'a' % o attribute {a newvalue} ::o::a % o a oldvalue
Also, is it possible for "object delete attribute a" to not complain if the attribute does not exist, may be via "-nocomplain" switch or just by default?
Thanks,
Victor
On Wed, Jun 29, 2011 at 3:51 AM, Stefan Sobernig stefan.sobernig@wu.ac.at wrote:
Victor,
%Object create o ::o %o attribute {a oldvalue} ::o::a %o a oldvalue %o attribute {a newvalue} ::o::a %o a oldvalue
Forgot to ask: Why do you take this path (changing the default of the attribute slot) in the first place? If you want "a" to have the value "newvalue" assigned, why don't you simply say:
o a newvalue
//s
Xotcl mailing list Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl