[Xotcl] nx parameters

Gustaf Neumann neumann at wu-wien.ac.at
Thu Dec 16 11:31:35 CET 2010


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.






More information about the Xotcl mailing list