proc xproc {pname arglist body} {
set preamble ""
foreach arg $arglist {
set arg [lindex $arg 0]
if {[string match "&*" $arg]} {
set barearg [string range $arg 1 end]
append preamble "upvar 1 \[set [list $arg]\] [list $barearg]\n"
}
}
proc $pname $arglist "$preamble#original body follows:\n$body"
}(Remark by AvL: I simplified the xproc-implementation, and made it more robust against nasty variable names) Here's a sample usage:
xproc myproc {&arr} {
foreach n [array names arr] {
puts "arr($n) => $arr($n)"
}
}
array set myarray {1 one 2 two 3 three}
myproc myarrayRS: Nice! I'd like to speak in defense of upvar, which is no black magic, but just a scoping mechanism. Like everything, references in Tcl are strings, implemented as variable names, which are valid in their scope. Now as proc variables normally have local scope (which is a good thing!), you have to dereference variables from other (only upper) scopes if required, and that is precisely what upvar does. And: even seeming innocent statements like
set i 0already contain a reference - to the variable "i". In general, every time you mention a variable name without prefixing it with $, you're working with a reference. (See Dangers of creative writing for a list of commands that use references, and possibly create new variables).[AvL: I've removed a suggestion of a change that has meanwhile been included, to avoid confusion.]See Implicit upvar for a later alternative to xproc, and use_refs
