[Xotcl] Static member functions?

Gustaf Neumann neumann@wu-wien.ac.at
Wed, 16 Apr 2003 20:35:16 +0200


On Wednesday 16 April 2003 08:30, Michael A. Cleverly wrote:
> (Disclaimer: I'm quite new to XOTcl & I have read the tutorial a couple
> times but maybe not enough.  :-)
>
> What's the XOTcl idiom/way for a static member variable (what snit, the
> only other OO Tcl package/extension I've used, would call a "type
> variable")?
>
> Contrived example: if I had a "Chapters" class, I'd like to have a single
> variable, accessible by all instances of the class, that kept track of the
> "current" chapter.  Suggestions?

 Most of the important things were already answered by Neophytos and Kristoffer.
 XOTcl does not need a special construct, since every class is an object
 as well, and variables kept in a class are nothing special. Note that a
 programmer can decide what kind of class he is referring to:
  - the class which is the type of the object (via "my info class")
  - the current class, which is currently active (via "self class")
 The type variable you are refering to is the first one.

 Often, when people start to use XOTcl, there come requests how to achieve
 private instance variables. These can be easily achived through variable
 traces. Maybe someone finds the following code helpful or interesting....

=================================================================
Object instproc private {instvar args} {
  foreach var $args {
    my trace variable $var rwu [list [self] private_check]
  }
  uplevel "my instvar $args"
}
Object instproc private_check {var sub op} {
  if {[string compare [self] [self callingobject]]} {
    if {[string equal "" [self callingobject]]} {
      set context "global context"
    } else {
      set context [self callingobject]->[self callingproc]
    }
    array set paraphrase {w written r read u unset}
    error "private member $var of [self] $paraphrase($op) from $context"
  }
}
=================================================================

 Using this two instprocs, private instvars of an object can be declared.
 This is not a perfect solution but works quite well.....

================================================================ 
Class C 
C instproc init {} {
  my private instvar x y
  set x 100
}
C instproc test {} {
  my set x 10
}
C instproc show {} {
  puts x=[my set x]
}

### test cases ###
C c1
c1 show
c1 test
c1 show
Object o1
o1 proc test0 {} { if {[catch {c1 set x 13} msg]} { puts "error: $msg" }}
o1 proc test1 {} { c1 instvar x; if {[catch {set x 13} msg]} { puts "error: $msg" }}
o1 proc test2 {} { if {[catch {c1 set x} msg]}    { puts "error: $msg" }}
o1 proc test3 {} { if {[catch {c1 unset x} msg]}  { puts "error: $msg" }}
c1 show
o1 test0
o1 test1
o1 test2
#o1 test3
c1 show
c1 set y 20
=======================================================

 If you want to use this test please apply the small patch below to 
 allow correct error propagation through traces in XOTcl. There seems
 to be a small bug in the actual tcl-versions, since Tcl_UnsetVar2
 (which is used by xotcl unset) does not seem to propergate 
 errors correctly from var traces as well....

=======================================================
--- xotcl.c~    Fri Mar 21 15:57:45 2003
+++ xotcl.c     Wed Apr 16 19:00:35 2003
@@ -5978,7 +5978,7 @@
    * "init").  */

   if (!(obj->flags & XOTCL_INIT_CALLED)) {
-    int newargs, result;
+    int newargs;
     /*
      * Call the user-defined constructor 'init'
      */
@@ -6986,8 +6986,7 @@
     Tcl_SetObjResult(in, result);
     return TCL_OK;
   } else {
-    return XOTclVarErrMsg(in, "Can't find result of set ",
-                         ObjStr(objv[1]), 0);
+    return TCL_ERROR;
   }
 }
=======================================================

-- 
Univ.Prof. Dr.Gustaf Neumann
Abteilung für Wirtschaftsinformatik
WU-Wien, Augasse 2-6, 1090 Wien