Tcl - passing arrays and strings in and back out of procs
Archive - Originally posted on "The Horse's Mouth" - 2009-10-22 06:08:11 - Graham EllisWhen you want to pass data INTO a proc in Tcl from a regular variable, you write the variable name with a $ in front of it in the code and the value is substituted. But this doesn't work if (a) you are passing an array (which cannot be expanded into a string or (b) you want to change the value in a variable, or pass a result back in it. So that's when you use upvar.
It works like this. You pass in the NAME of the variable that you want to set / change, and then you use upvar to say "the variable called harry in this proc is the same as the varaible named in the $text varaible passed in from the level above which is the same as the mytext variable in that calling code." (Clearly, the names I have used are examples, and from this piece of code:
proc dress {text} {
upvar $text harry
set harry "<h1>$harry</h1>"
return [string length $harry]
}
set mytext "Hello World"
set sz [dress mytext]
puts "$sz $mytext"
Here's a sample that shows how this runs:
Dorothy-2:oct09 grahamellis$ tclsh tcl/dresser
20 <h1>Hello World</h1>Dorothy-2:oct09 grahamellis$
When you start looking at the built in commands in Tcl itself, you'll see how significant this is ... so many of them take parameters from which you omit the $ character and that's a sure sign that the proc concerned does / will / might change the ingoing value. Examples that come to my mind include foreach, regsub, regexp, incr, and even set!
The example above is on our web site here. This is a subject that's not an obvious one when you first come to it, and there are all sorts of other nasty things you can do with upvar and uplevel and so we spend a good time explaining and trying it out on both our Tcl and Expect programming and our Learning to program in Tcl courses.
Further examples: here, here (passing back an array), and here.
Tcl offers further flexibility in proc (function) calls too - optional parameters are illustrated here, calling procs with a variable number of parameters here, using global variables (OK to use occasionally!) here and you can even use uplevel to run code in the level above - very specialised use, see example here