I've been using namespaces to structure data of late, and I've generated a few procedures I thought others might find helpful.
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.
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] } }
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] }