3

In ns2, I declared a simple array using

array set ktree {}   

then I tried to use it as a GOD variable as

create-god $ktree

but this gives the error

can't read "ktree": variable is array
while executing
"create-god $ktree {}"

Any help is greatly appreciated.

Monty Swanson
  • 695
  • 16
  • 41

1 Answers1

2

In Tcl, $varName means “read from the variable called varName” and is not a general reference to the variable (unlike some other languages, notably Perl and PHP, which do rather different things). Reading from a whole array, instead of an element of that array, is always an error in Tcl.

To pass an array to a command, you pass the name of that array in. It's then up to that command to access it as it sees fit. For procedures and methods written in Tcl, it'll typically involve upvar to link the array into a local view. (Things written directly in C or C++ have far fewer restrictions as they don't automatically push a Tcl stack frame.)

Note however that the command must be expecting the name of an array when you pass that name in. (Good programmers will document this fact, of course.) Whether create-god does, I really have no idea; it's not a general Tcl command but rather something that's more specific. (Part of ns2? Or maybe your own code.)


Example of passing in an array

An example of passing in an array by name is the parray command that should be part of every Tcl distribution. It's a procedure that prints an array out. Here's the source code without a few boiler-plate comments:

proc parray {a {pattern *}} {
    upvar 1 $a array
    if {![array exists array]} {
        error "\"$a\" isn't an array"
    }
    set maxl 0
    set names [lsort [array names array $pattern]]
    foreach name $names {
        if {[string length $name] > $maxl} {
            set maxl [string length $name]
        }
    }
    set maxl [expr {$maxl + [string length $a] + 2}]
    foreach name $names {
        set nameString [format %s(%s) $a $name]
        puts stdout [format "%-*s = %s" $maxl $nameString $array($name)]
    }
}

The key thing here is that we first see upvar 1 to bind the named variable in the caller to a local variable, and a test with array exists to see if the user really passed in an array (so as to give a good error message rather than a rubbishy one). Everything else then is just the implementation of how to actually pretty-print an associative array (finding out the max key length and doing some formatted output); it's just plain Tcl code.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • @Chhama Yes, well probably. Depends on what you mean by that. Doing justice to what you're asking will take me more than I can fit in a comment; could you ask it as a proper question? – Donal Fellows Jun 03 '13 at 08:19
  • im not sure it will be accepted as a proper question :) . What im basically trying to do is to create a weight-balanced AVL Tree using tcl without using OTcl. My plan involves structures but i read a structure cannot contain another structure so Im kind of at a loss here. – Monty Swanson Jun 03 '13 at 11:37