When programming, one has several choices for getting information into a procedure:
In Tcl, variables containing strings (whether in list, handle, or normal string format) are typically passed by value. This means that the called procedure never really knows the name of the variable containing the value - and thus it cannot directly modify that value. Instead, most Tcl scripting looks like:
set val [lindex $val 2]
In other words, the value of a variable changes after the command has calculated a new value.
Entire arrays, however, are not currently able to be passed by value to a Tcl procedure (despite the damage this does to the EIAS dogma). This is due to Tcl currently passing only 'string' type data as arguments, and arrays not having a simple string notation for their value.
Instead, there are two choices for passing arrays both "into" and "out of" proc-s:
If 8.5 or greater is available, a third alternative is to
If you're willing to use extensions, a whole range of additional "instead of an array, use ..." possibilities:
proc top {} { array set thisarr { en "Hi everybody" de "Guten Morgen allerseits" } puts "top: english=$thisarr(en)" puts "top: german=$thisarr(de)" set newarrlist [bottom [array get thisarr]] array unset thisarr array set thisarr $newarrlist puts "top: latin=$thisarr(la)" } proc bottom {arrlist} { array set thatarr $arrlist puts "bottom: english=$thatarr(en)" puts "bottom: german=$thatarr(de)" set thatarr(la) "Salvete omnes" return [array get thatarr] }
Note that the cost of [array get] and [array set] is not as bad as it looks. Because in the implementation objects are reference-counted and the intermediate is represented as a real list, the content of the array keys and values are never actually copied. Only the array structure itself is recreated by [array set].
proc myparray {ea} { upvar $ea a puts "-------" parray a; # or any other manipulation on $a(..) puts "-------" } myparray ::env
Removing keys with empty values from an array: Note that the array name is passed in, associated with local variable arr. The unsetting of elements with empty value, done in arr, in fact happens in the caller's original array.
proc cleanArray arrName { upvar 1 $arrName arr foreach key [array names arr] { if {$arr($key) == ""} {unset arr($key)} } }
KBK (16 April 2002) - In Tcl 8.3 and beyond, it's much faster to say, simply:
array unset arr
rather than looping through the result of [array names]. In earlier versions, you can say
unset arr array set arr {}
but that has the disadvantage of messing up any traces that are extant on the array. RS: Indeed, but this clears the whole array - the specified task was to remove only those elements which have empty values.
ken: How do i create a namespace variable for array set variables? Is it possible ? Cause i am creating a couple of procedures which need access to their global variables?
Lars H: Accessing namespace variables work the same for arrays as for ordinary variables; one can use variable, global, or the fully qualified variable name. Does this answer your question?
NEM: To illustrate:
namespace eval foo { variable myarray array set myarray { ... } proc bar value { variable myarray set myarray(element) $value } }
It's important to use "variable" to declare the variable in the right namespace, to avoid the dangers of creative writing.