Version 1 of Forwarding local namespace proc calls to instance methods in TclOO

Updated 2011-02-21 09:26:29 by dkf

Here is my original question:

I think I'd like to have the methods of my object appear in the command resolution path (when within a method). I'd like to write a configuration mini language where the commands of the mini language are the methods of my class. When I pass a script to one method of the object, it would eval it and have the other methods get called with out prefixing with self or my.

Where do the objects commands reside? Can they be invoked from the classes namespace in the context of the object's?


Something to note is that setting up the forwarding procs must happen at instance constructor time, since the procs must be in the instance's namespace. The code which declares these procs must be called from the constructor, or the constructor itself must be modified (in a subclass of class maybe?). Here is my more refined solution:

 # Create procs in the objects namespace that forward calls to instance methods.  This
 # allows methods to be called without [self] and [my].
 #
 proc nsproc args {
    foreach proc $args {
        proc [uplevel 1 { namespace current }]::$proc args [subst { tailcall my $proc {*}\$args }]
    }
 }

 oo::class create X {
    constructor {} {
        nsproc a b c
    }

    method a {} { b }
    method b {} { puts XXX }
 }

 X create x
 x a

My first rough answer, basically the same as above but less concise:

Here is a solution, maybe there is something easier? I need to learn to add class defining commands to help me with these wrappers I've been asking about.

 oo::class create config-language {
    variable Data

    constructor {} {
        set Data 8

        # Splice the object's "=" command to a proper invocation.  A series
        # of declarations like this would "export" the mini language to the 
        # objects namespace, where they now appear to be in the command 
        # resolution path. 
        #
        proc ::[namespace current]::= {} { my = }
    }

    method = {} { puts "fart $Data" }
    method x {} {

        # x invokes a sister method without prefix
        #
        =
    }
 }

 config-language create instance1

 instance1 x