TCL pretty much treats everything as a string or list. Crafting complex data structures can be done (put lists of lists together and define some get() set() procedures for working with the data). What if you don't want to do that?

According to the tcl wiki, the canonical answer looks like the following, using a list as the key for the associative array:

array set commands [list \ [list cisco ping ] "ping %s source %s" \ [list netopia ping ] "ping %s source %s" \ [list siemens ping ] "ping -I %s %s" \ ]

That data structure looks workable, however the order of the format arguments matters, and the siemens ping command has the reverse order of the others. We could create a wrapper function... and remember to call it to format the command correctly. We can avoid that cognitive load by implementing lambda() in TCL:

# XXX have to always pass in a list proc lambda {arg body} { set name [format "%s%s" $arg $body] ; # ensure global uniqueness proc $name $arg $body return $name } array set commands [list \ [list cisco ping ] [lambda x { format "ping %s source %s" [lindex $x 0] [lindex $x 1] } ] \ [list netopia ping ] [lambda x { format "ping %s source %s" [lindex $x 0] [lindex $x 1] } ] \ [list siemens ping ] [lambda x { format "ping -I %s %s" [lindex $x 1] [lindex $x 0] } ] \ ] puts [$commands([list cisco ping]) [list 1.1.1.1 2.2.2.2] ] puts [$commands([list netopia ping]) [list 1.1.1.1 2.2.2.2] ] puts [$commands([list siemens ping]) [list 1.1.1.1 2.2.2.2] ]

Yielding the following ...

ping 1.1.1.1 source 2.2.2.2 ping 1.1.1.1 source 2.2.2.2 ping -I 2.2.2.2 1.1.1.1

Now to fill out a whole lot more commands.... ;)