Hello Gustaf,
Although your examples do seem to work on Object objects, the Class instances do not work right. Here is a snippet from your examples:
nx::Class create C { # Create attributes "x" and "y" and script the initialization of # these attributes. :attribute x { set :timestamp [clock clicks] } :attribute y { set :timestamp [clock clicks] } :create c1 }
# Print for every slot object the value of the timestamp, if it # exists. proc print_slots_and_timestamps {obj} { foreach slot [$obj info lookup slots] { if {[$slot eval {info exists :timestamp}]} { puts "$slot created at [$slot eval {set :timestamp}]" } } } print_slots_and_timestamps c1
######################################################
if I do [C create c2] and then [print_slots_and_timestamps c2], the actual output is still for instance c1, not c2, also all instances of C class have the following slot in them, which doesn't seem right: ::C::slot::x . Shouldn't it be something like ::c1::slot::x, ::c2::slot::x ?
Thanks
On Thu, Dec 16, 2010 at 2:31 AM, Gustaf Neumann neumann@wu-wien.ac.at wrote:
Dear Victor,
here is a scripted writeup to address your questions.
-gustaf neumann
package req nx::test nx::Object create o
# The method setter registers an accessor method for instance # variables. It provides "set" and "get" operations and value # checking.
# Register accessor named x o setter x
# Use the accessor method x as setter # (set instance variable x to 1; returns 1) ? {o x 1} 1
# Use the accessor method x as getter # (get the value of the instance variable x; returns 1) ? {o x 1} 1
# Define a setter with a value constraint o setter x:int ? {o x 3} 3 ? {o x a} {expected integer but got "a" for parameter "x"}
# The accessor function can be realized with some more typing as well # via the following method. So, the method "setter" does not provide # any additional functionality in terms of expressability of the # language.
o public method y {value:int,optional} { if {[info exists value]} { return [set :y $value] } else { return [set :y] } }
? {o y 3} 3 ? {o y a} {expected integer but got "a" for parameter "value"}
# Why are accessor function at all provided since instance variables # can be accessed as well without these? In nx it is easy for an # object to access the own instance variables via variable resolvers # (variable names starting with a single colon), butmore work to # access the variables of other objects. One can use e.g. the method # "eval" to execute a script in the context of an object (and to be # able to use the variable resolver).
? {o eval {set :x 2}} 2
# So, an accessor method makes the access of public variables easy, it # provides the value constraints, one can use interceptors for # tracing, refinement, etc.
# Ok, why do we need attributes?
# Attributes (as defined by nx) provide all functionalities provided # by the setter methods plus # - some attribute life-cycle management (e.g. default values), and # - arbitrary meta-data
# For example, we can define an integer attributed named "z" with a # default value.
o attribute {z:int 123} # return the default value ? {o z} 123 ? {o z a} {expected integer but got "a" for parameter "z"}
# The example above is an object specifc attribute. In most # situations, attributes are defined on the class level. Attributes # are inherited to subclasses (setters certainly as well).
nx::Class create Employee { :attribute serial_number:int,required } nx::Class create Manager -superclass Employee { # Project names are upper case, provided as an list, which might be # empty and are per default initialized to the empty list. :attribute {projects:upper,0..n {}} }
Manager create joe -serial_number 4711
# What about the meta-data? I want to use e.g. very special meta-data, # such as e.g. time-stamps.
# The method "attribute" creates so-called slot objects, which are in # turn nx objects. These slot objects can be initialized like all # other nx objects in a scripted way.
nx::Class create C { # Create attributes "x" and "y" and script the initialization of # these attributes. :attribute x { set :timestamp [clock clicks] } :attribute y { set :timestamp [clock clicks] } :create c1 }
# Print for every slot object the value of the timestamp, if it # exists. proc print_slots_and_timestamps {obj} { foreach slot [$obj info lookup slots] { if {[$slot eval {info exists :timestamp}]} { puts "$slot created at [$slot eval {set :timestamp}]" } } } print_slots_and_timestamps c1
# # Ok. What if I want to use a time-stamp for every attribute of my # application without having to write this for every occurance? # # Well, use the force, luke. Remember, we have quite a powerful # underlying framework, supporting e.g. mixin, dynamic call # definitions, etc.
::nx::Attribute mixin [Class new { :method init {} { set :timestamp [clock clicks] next } }]
nx::Class create D { # Create attributes "x" and "y" and script the initialization of # these attributes. :attribute x :attribute y :create d1 }
print_slots_and_timestamps d1
# # What if i want to use different kinds of attributes, such as # e.g. persistent attributes and non-persistent attributes, etc.? How # can i define my on slotclasses if i need? # # Per default, attributes are of the class ::nx::Attribute. One can # certainly define subclasses of this class and specify these classes # during attribute creation. Since "attribute" is technically a # method, the syntax is slightly different to the usual object # creation. # # We define now "MyAttribute" as a subclass of ::nx::Attribute with an # additional attribute named timestamp. The timestamp has the actual # timestamp as default. # ::nx::MetaSlot create MyAttribute -superclass ::nx::Attribute { :attribute {timestamp "[clock clicks]"} }
# Use this type of attribute: nx::Class create E { :attribute x -slotclass MyAttribute :attribute y -slotclass MyAttribute :create e1 }
print_slots_and_timestamps e1
# A final question: i see that "attribute" is more powerful then # "setter". Do I need as an enduser the method "setter" at all? # # No. I think, we could safely remove it from the default method set # for the final release. # # One other observation during this writeup: maybe "slotclass" is to # crude, we could use "class" or "type" instead (at some earlier # state, we could not use technically "class"). We will overthink # this.