A. Dictionaries in Tcl

Note

This text is extracted from the book: Tcl 8.5 Networking Programming. (Tcl 8.5 Networking Programming, 2010)

Dictionaries are somewhat similar to arrays in that they keep mapping between key and value, but a dictionary is treated as an object. Dictionaries can also be truly multi-dimensional. The other difference is that dictionaries are significantly faster than arrays.

The new command dict was introduced to operate on dictionaries. The command is natively present in Tcl 8.5, but it can be also used in Tcl 8.4 by adding the dict package.

To create a dictionary, use the dict create command with the equal number of arguments; alternately, keys and values:

set myDict [ dict create key1 value1 key2 value2 key3 value3 ]

Figure A.1. The command above creates a dictionary with three mappings and stores it in the myDict

The command above creates a dictionary with three mappings and stores it in the myDict

To access the mapped value, you can use the dict get command:

% dict get $myDict key2
value2

This command (dict create) also allows us to create multi-level dictionaries:

set myDict [ dict create key1 [ dict create key2 [ dict create key3 value]]]

Figure A.2. Variable myDict with a multi-level structure.

Variable myDict with a multi-level structure.

But in this case the command to access a third-level variable is used in the following way:

% dict get $myDict key1 key2 key3
value

Dictionaries can be passed between procedures, for example:

proc createDict {} {
    set value [dict create]
    dict set value firstValue 1
    dict set value otherValue 2
    return $value
}

A.1. Storing raw Tcl values

In Tcl, it is easy to store data structures like lists or dictionaries in flat text file.

First, let's demonstrate how to write to and read from a list:

#writing
set book1 [list {Learning Nagios 3.0} 978-1-847195-18-0]
set book2 [list {Tcl Network Programming} 978-1-849510-96-7]
set books [list $book1 $book2]

puts [lindex [lindex $books end] 0]

set channel [open data.txt w]
puts $channel $books

close $channel

#reading
set channel [open data.txt r]
set books [read $channel]
close $channel

puts [lindex [lindex $books end] 0]

books variable is a list of two lists, each one containing the title and ISBN number, respectively. Before saving, we print out the name of the second book. Then, the $books is written to data.txt file, and in the next lines its contents are read and stored again into the books variable. It is the unique Tcl feature that allows treating lists as normal text strings and vice versa, therefore after reading the file we are able to access the variable in a list-like way and print the same title again, for verification:

{{Learning Nagios 3.0} 978-1-847195-18-0} {{Tcl Network Programming} 978-1-849510-96-7}

Next, let's do the same thing, but with a dictionary object:

dict set books book1 title {Learning Nagios 3.0}
dict set books book1 isbn 978-1-847195-18-0
dict set books book2 title {Tcl Network Programming}
dict set books book2 isbn 978-1-849510-96-7

puts [dict get $books book2 title]

set channel [open data2.txt w]
puts $channel $books
close $channel

set channel [open data2.txt r]
set books [read $channel]
close $channel

puts [dict get $books book2 title]

Thanks to Tcl's way of internally treating of structures like lists or dictionaries, no additional conversion or serialization is required. As you can see, the procedure is identical, basically puts and read commands handle all the storage issues. In this case, the output is identical as in previous example:

Tcl Network Programming

Note

Limitations

Note that such a way of storing and retrieving data works only with text information. If you have some other kind of data in your list, for example handles to objects, its meaning would be lost.

Encoding

We did not mention encoding in this section, it will not be necessary if you are using only one platform. If you are aiming for cross platform portability, we recommend the following configuration of the channel:

fconfigure $channel -translation lf -encoding binary

Another option is to set encoding to utf-8, which will preserve all Unicode data as well as binary data. For example:

fconfigure $channel -translation lf -encoding utf-8

These are only the basics, there are also many other operations available for dictionaries, these can be compared to the operations for arrays described earlier, because their concepts are similar.

For the complete documentation of the dict command, you can refer to www.tcl.tk/man/tcl8.5/TclCmd/dict.htm.