Updated 2013-06-15 19:30:11 by dkf

I've been using namespaces to structure data of late, and I've generated a few procedures I thought others might find helpful.

vars edit

One annoying thing is the variable command - you can't just give it a list of variables you want the code to access in a namespace, you have to have multiple variable statements, one for each, as the semantics don't take a list per se but must alternate with an initializer. With:
proc vars { args } {
   foreach var $args {
      uplevel "variable $var"
   }
}

You can say
vars a b c

and that is the equivalent of
variable a
variable b
variable c

A minor convenience but makes for more concise code.

access edit

Not infrequently, I find myself wanting to execute something in a namespace but to access vars in a surrounding proc context. Using {} defeats just calling $whatever in the namespace since the proc variables are not visible. You either have to use " and " - thereby putting one in quoting hell - or you have to have a prefix and body where the prefix is done with quotes and then appended to the body, to pass in vars. Here's a nicer way to do that:
proc access { args } {
   foreach var $args {
      set t [split $var >]
      if {[llength $t] == 2} {
         set left [lindex $t 0]
         set right [lindex $t 1]
      } else {
         set left $var
         set right $var
      }
      set temp "[uplevel uplevel set $left]"
      regsub -all {"} $temp {\"} temp
      set cmd "set $right \"$temp\""
      uplevel $cmd
   }
}

with this you can do:
proc foobar { this that args } {
   namespace eval foo {
      access args this that
      set arglist $args
      puts "I was passed $this and $that"
   }
}

and it works as expected. Access also allows you to rename things.
proc foobar { this that args } {
   namespace eval foo {
      access args>arglist this>mythis that>mythat
      puts "I was passed $arglist, $mythis and $mythat"
   }
}

SEH -- Been messing around a lot lately with juggling levels and access, so I thought I'd try my hand:
proc access {args} {
    set nspace [uplevel namespace current]
    foreach arg $args {
        lassign [split $arg >] left right
        set $left [uplevel 2 set $left]
        set ${nspace}::[lindex [concat $left $right] end] [set $left]
    }
}

alink edit

KPV -- When debugging via a console, I use the following function to create linked variable in the global namespace to a variable in a namespace. For example, typing alink ::foo::bar will create the variable bar which is the same as ::foo::bar. This allows me to paste in code from a procedure in a namespace into the console and have it access the correct variables.
proc alink {var} {
    uplevel \#0 upvar \#0 $var [lindex [split $var ":"] end]
}


[Category Tools][Category Namespaces]