Version 11 of Tiny OO with Jim

Updated 2005-03-16 23:03:59 by suchenwi

if 0 {Richard Suchenwirth 2005-03-16 - Here's a little experiment in OO using the Jim feature that procs and lambdas can have a "closure" (a set of static variables) associated.

(Note that this code does not run on regular Tcl interpreters - use Jim instead!)

This way, the only physical location of an object is its lambda - rename it away as destructor. No namespaces needed (or possible in Jim ;^)}

#-- Here's a "constructor" the hard (bare-bones) way:

 proc Account args {
    lambda {method args} {{balance 0}} {eval Account'$method $args}
 }

if 0 {Alternatively, if you want to use more than one class, here's factoring out the generic part. It also adds an introspection method for the names of instance vars:}

    proc class {name instvars} {
        proc $name args \
          [list lambda {method args} $instvars "eval $name'\$method \$args"]
        proc $name'vars {} [list return [lmap i $instvars {lindex $i 0}]]
    }

#-- Let's re-create a first class, the usual bank account, with one instance variable:

 class Account {
    {balance 0}
 }

#-- Bare-bone methods (procs) need to upvar the instance vars they need:

 proc Account'deposit amount {
    upvar 1 balance balance
    set balance [+ $balance $amount]
 }

#-- Here's a wrapper to implicitly do those upvars in methods:

 proc method {class name argl body} {
   proc $class'$name $argl "foreach i \[\[self\] vars\] {upvar 1 \$i \$i} \n$body"
 }

#-- Methods can be written slicker now:

 method Account see {} {set balance}

 method Account withdraw amount {
    if {($balance-$amount)<0} {error "can only withdraw $balance"}
    set balance [- $balance $amount]
    puts now:[[self] see]
 }

if 0 {"Who am I?" is a deep philosophical question. Inside methods, it's easily answered:}

 proc self {} {lindex [info level -2] 0}

if 0 {Now testing:

 set a [Account]
 puts a:$a
 $a deposit 100
 puts "deposit 100 -> [$a see]"
 $a withdraw 40
 catch {$a withdraw 1000} res
 puts $res

shows on stdout

 a:<reference.<functio>.00000000000000000000>
 deposit 100 -> 100
 now: 60
 can only withdraw 60

SS Very nice! It seems to me a very natural hack to try to implement objects via closures. Also your way to do the dispatch is impressive ;)


Arts and crafts of Tcl-Tk programming | Category Object Orientation | Category Jim }