views:

221

answers:

2

If I have a proc that needs to return an array to its caller, what is the best way to do this?

I following code does not work in Tcl due to inability to $ an array variable:

proc mine {} {
  array set foo { red 1 blue 2 green 3 }
  $foo
}

tcl> set foo [mine]
Error: can't read "foo": variable is array

Alternatively this doesn't work either:

proc mine {} {
  array set foo { red 1 blue 2 green 3 }
  array get foo
}

tcl> set foo [mine]

tcl> puts $foo(blue)
Error: can't read "foo(blue)": variable isn't array

This leaves me with the probably inefficient:

proc mine {} {
  array set foo { red 1 blue 2 green 3 }
  array get foo
}

tcl> array set foo [mine]
2

Or the obscure:

proc mine {varName} {
  upvar $varName localVar
  array set localVar { red 1 blue 2 green 3 }
}

tcl>unset foo
tcl>mine foo
tcl>puts $foo(blue)
2

Is there a better way to do this, or if not, which is the most efficient?

A: 

My preference, if you need to use arrays, is the [array get/set] combo you showed:

proc mine {} {
  array set foo { red 1 blue 2 green 3 }
  array get foo
}

tcl> array set foo [mine]
2

That being said, if you're using Tcl 8.5 or later, you can consider using dicts. They're generally going to be faster and cleaner.

RHSeeger
+3  A: 

I think you've answered your own question. Simply put, you cannot return an array. There are options, which you explained in your question:

1) you can return the array value, and convert it back to an array in the caller 2) you can use upvar in your procedure so that the caller passes in the name of an array which you can then modify.

If you are using tcl 8.5 you might want to consider switching to using a dict. Dicts are first class objects that can be passed around, returned from procedures, etc.

Bryan Oakley