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

Re: [Xotcl] constant/immutable property

From: Stefan Sobernig <stefan.sobernig_at_wu.ac.at>
Date: Mon, 02 Jan 2012 17:28:32 +0100

Victor,

> Maybe this simple study helps already

I just recovered a variation of Gustaf's study which I had used in
previous projects of mine. The study below differs with respect to
enforcing the "immutability" (prohibiting vs. preserving state) and adds
handling of variable unsets. It slightly optimizes over the method
dispatch for write traces (using ::nsf::set::var), however, it also
comes at extra costs (doubled variable writes).

It can be easily extended for supporting basic introspection, kinds of
"/obj/ info immutables" or the like ...

//stefan

package req nx
package req nx::test
package req nx::trait

::nx::Class create C {
   :require trait nx::traits::callback
   #
   # Make selected (by default, all currently defined) variables of an
   # object immutable
   #
   :public forward immutable %self traces add

   #
   # Make selected (by default, all currently defined) variables of an
   # object mutable (again ...)
   #
   :public forward mutable %self traces remove

   :protected method traces {op args} {
     foreach varName [expr {[llength $args] ? $args : [:info vars]}] {
       set writeCmdPrefix [list ::nsf::var::set [self] $varName [set
:$varName]]
       set unsetCmdPrefix "$writeCmdPrefix; [:callback immutable $varName]"
       ::trace $op variable :$varName write "$writeCmdPrefix;#"
       ::trace $op variable :$varName unset "$unsetCmdPrefix;#"
     }
   }
   :create c1 {
     set :x 1
     set :y 2
   }
}

#
# c1 is mutable ...
#
? {c1 eval {set :x}} 1
? {c1 eval {set :y}} 2
? {c1 eval {set :x 5}} 5
? {c1 eval {set :x}} 5
? {c1 eval {unset :y; set :y}} {can't read ":y": no such variable}
? {c1 eval {set :y 4}} 4
? {c1 eval {set :z 3}} 3

#
# c1 becomes immutable ...
#
c1 immutable

? {c1 eval {set :x}} 5
? {c1 eval {set :y}} 4
? {c1 eval {set :x 1}} 5
? {c1 eval {set :x}} 5
? {c1 eval {unset :y; set :y}} 4
#
# Subsequent unsets are handled ...
#
? {c1 eval {unset :y; set :y}} 4
? {c1 eval {set :y 2}} 4
? {c1 eval {set :z 3}} 3

#
# c1 becomes mutable (again ...)
#

c1 mutable

? {c1 eval {set :x}} 5
? {c1 eval {set :y}} 4
? {c1 eval {set :x 1}} 1
? {c1 eval {set :x}} 1
? {c1 eval {unset :y; set :y}} {can't read ":y": no such variable}
? {c1 eval {set :y 2}} 2
? {c1 eval {set :z 3}} 3