When programming, one has several choices for getting information into a [proc]edure: * pass an argument value at invocation * pass a variable reference (usable via uplevel or upvar) at invocation * access a local variable * access a non-local (global, environment, outside the frame) variable * request input from the user or from a file/socket/etc. 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 [array]s both "into" and "out of" [proc]-s: * serialization (generally converting the values of an array into a list with "array get ...") * local proxying of an external variable by use of [upvar] or occasionally [uplevel] If 8.5 or greater is available, a third alternative is to * use a [dict] instead of an array. If you're willing to use extensions, a whole range of additional "instead of an array, use ..." possibilities: * [Tclx] keyed lists. * the structure command from the [megapkg structure extension]. * ... **Examples** * Create an array from pairlist: ''array set A {city Hamilton state TX zip 34567}'' * Serialize an array to pairlist: ''set L [[array get A]]'' * Copying an array: ''array set B [[array get A]]'' [[but we have to show explicitly how this relates to proc-to-proc communication]] ***Example of passing an array by serializing the array to pair list*** ====== 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]]. ---- ***Example of local proxying of an external variable *** ====== 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]. <> Data Structure | Tutorial