No registered users in community xowiki
in last 10 minutes
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.
>
>
>
>
>
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.
>
>
>
>
>