View · Search · Index
No registered users in community xowiki
in last 10 minutes

Re: [Xotcl] nx parameters

From: Victor Mayevski <vitick_at_gmail.com>
Date: Sat, 18 Dec 2010 23:18:22 -0800

Thank you very much Gustaf for taking your time to explain this.




On Thu, Dec 16, 2010 at 2:31 AM, Gustaf Neumann <neumann_at_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.
>
>
>
>
>