- 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.
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:
- 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
- use a dict instead of an array.
- Tclx keyed lists.
- the structure command from the megapkg structure extension.
- ...
Examples edit
- 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 arrrather 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.