please find below a snippet of code that passes an array, manipulates the array, but i cannot return the new version of array.
here is the snippet :
proc get_mroute_active { &multicast } {
upvar ${&multicast} MULTICAST ;
set group -1 ;
set src -1 ;
set mcast_group_source_id -1 ;
set MULTICAST($mcast_group_source_id,id) $mcast_group_source_id ;
set MULTICAST($mcast_group_source_id,mcast_group) $group ;
set MULTICAST($mcast_group_source_id,mcast_source) $src ;
puts [array size MULTICAST] ;
parray MULTICAST ;
}
array set multicast { } ;
get_mroute_active [array get multicast] ;
puts [array size multicast] ;
parray multicast ;
And the output of the code is :
3
MULTICAST(-1,id) = -1
MULTICAST(-1,mcast_group) = -1
MULTICAST(-1,mcast_source) = -1
0
Could you please help show me how the “MULTICAST” variable can be assigned to “multicast” ?
The short answer is: you can’t return an array from a procedure as arrays are not values — they are peculiar named collections of named values.
There are several ways to deal with this:
The usual approach is to pass arrays by names and make the called procedure modify the array in place. For instance, the code
will print “2” as the procedure
foomodified a specific value in the specified array in the caller’s scope.Notice how the caller passed the name of an array, “x”, instead of “its value” (as you cannot extract a value from an array; but see below) and then the called procedure bound a local variable to that array by its name using the
upvarcommand.The other approach is to employ
array getandarray setcommands to extract keys and values from arrays and populate arrays with keys and values, respectively. For instance:would print
The
array getcommand, given an array, returns a flat list with its keys and their respective values interleaved. This way you can return the contents of an array from a procedure and then make the caller do whatever it wishes with these contents, for instance, use thearray setcommand to populate another array in its scope (possibly the same which has been passed to that procedure in the first place).Note that
array sethas merge semantics: it does not empty the target array before inserting/replacing its values using the source list.The third (and may be the best) approach is to use dictionaries which are key/value maps as arrays do but are themselves values, so they can be passed around freely as other values. This requires Tcl 8.5 or later (in Tcl 8.4, you can use a backport of this code in the form of a package. With
dicts you get it like this:which would print “one 2” as the procedure modified the original dictionary then returned it and then the caller assigned it to another variable.