What: dictionary

 Where: http://www.purl.org/net/bonnet/pub/dictionary.tar.gz 
 Description: Implementation of a Tcl dictionary object type.
        A dictionary is equivalent to an array that is a first class
        object which can be used as proc arguments, inside other
        objects, etc.  Its contents looks like a list to Tcl commands,
        but internally things are stored similar to a hash.
 Requires: Tcl 8.2 or newer.  Currently at v1.0.1.
 Updated: 01/2000
 Contact:  mailto:[email protected]

Here is the usage guide from the package

Using the package

To use the package, simply add "package require dictionary" to your scripts. It
will register a new command "::dictionary" in the global namespace. This command
in turn provides a number of subcommands that operate on dictionary variables 
and objects.

List of subcommands

        "add",          "array",      "create",        "exists",
        "foreach",      "get",        "merge",         "names",
        "set",          "size",       "subtract",      "unset"

 * Dictionary creation

    They build new dictionary objects.

    dictionary create ?list?
    dictionary create ?key value ...?
        Return a new dictionary initialized with the specified
        arguments, either inline:

                set d [dictionary create 1 foo 2 bar]

        or as one even-sized list:

                set d [dictionary create [list 1 foo 2 bar]]

        Dictionaries can be used as an even-sized list:

                set d2 [dictionary create $d]

        But in this case it is faster to do:

                set d2 $d

        "dictionary create" is similar to the "list" command.

* Dictionary value access

    These are immutable methods and thus return new objects from existing ones, 
    like concat or lrange.

    dictionary size dict

        Query size of dictionary.

    dictionary get dict pattern

        Return a new dictionary from selected elements of another one.

    dictionary exists dict keyName

        Return whether the given key exists in the dictionary.

    dictionary names dict ?pattern?

        Return a list of keys that match the given pattern. If no pattern
        is specified, return all the keys.

    dictionary merge dict dict
    dictionary merge dict ?key value ...?

        Return a new dictionary made of the union of both dictionaries

    dictionary substract dict dict
    dictionary substract dict ?key value ...?

        Return a new dictionary made of the first dictionary elements
        minus the second's

* Dictionary variable access

    These are similar to set or lappend in the sense that they alter the value 
    of a variable.

    dictionary set varName keyName ?newValue?

        Query or set the value of an element named keyName in
        dictionary variable varName.

    dictionary unset varName keyName ?keyName ...?

        Unset elements with the given key names in dictionary variable
        varName .

    dictionary add varName key value ?key value...?
    dictionary add varName list

        Add specified elements to dictionary variable varName.
        Here list can also be a dictionary.

* Dictionary iteration

    dictionary foreach {keyName valueName} ?{keyName valueName} ...? command

        Iterate over a dictionary's keys and values. This is very similar to the 
        "foreach" Tcl command, except that it needs exactly two variables to be 
        specified for each dictionary. Moreover, it causes no type shimering 
(dictionaries are not converted to lists).

* Dictionary interface to arrays

    These 2 methods don't provide extra functionality over existing array 
    get/set methods, but the binary extension will provide optimizations given 
    that array methods expect lists and thus may create object type shimmering. 
    Dictionary methods won't create shimmering.

    dictionary array get arrayName ?pattern?

        Return a new dictionary with elements of array arrayName.
        An optional pattern is used to restrict elements by key.

    dictionary array set arrayName dict
    dictionary array new arrayName dict

        Fill array arrayName with dictionary dict's elements. The
        "new" form unsets any existing variable first.

See also http://purl.org/tcl/tip/111.html

This documentation does not appear to be compatible with the dictionary package included with ActiveTcl. ActiveTcl provide a 'dict' command (as opposed to 'dictionary') and dict does not support 'add' as a subcommand. There may be other inconsistencies. (Perhaps this entry should be changed to a short warning at the top of the page.)

See wordnet if you wanted a pointer to a traditional language dictionary type piece of software.

RS 2006-05-31: As data structures, dictionaries (taken as rectangular matrices of strings) can be well represented as a list of lists. Here is code for pretty-printing such a list, the resulting string looking (in fixed-pitch font only) like a table again:

 proc fmtable table {
    set maxs {}
    foreach item [lindex $table 0] {
        lappend maxs [string length $item]
    foreach row [lrange $table 1 end] {
        set i 0
        foreach item $row max $maxs {
            if {[string length $item]>$max} {
                lset maxs $i [string length $item]
            incr i
    set head +
    foreach max $maxs {append head -[string repeat - $max]-+}
    set res $head\n
    foreach row $table {
        append res |
        foreach item $row max $maxs {append res [format " %-${max}s |" $item]}
        append res \n
    append res $head

#-- Testing:

 set data {
    {1 short "long field content"}
    {2 "another long one" short}
    {3 "" hello}
 puts [fmtable $data]

#-- shows

 | 1 | short            | long field content |
 | 2 | another long one | short              |
 | 3 |                  | hello              |

Extended version, with the framing lines optional:

 proc fmtable {table {lines 0}} {
    set maxs {}
    foreach item [lindex $table 0] {lappend maxs [string length $item]}
    foreach row [lrange $table 1 end] {
        set i 0
        foreach item $row max $maxs {
            if {[string length $item]>$max} {
                lset maxs $i [string length $item]
            incr i
    if $lines {
       set head +
       foreach max $maxs {append head -[string repeat - $max]-+}
       set res $head\n
       set sep |
    } else {set sep ""}
    foreach row $table {
        append res $sep
        foreach item $row max $maxs {append res [format " %-${max}s $sep" $item]}
        append res \n
    if $lines {append res $head}
    set res

#-- Testing the two modes:

 % fmtable {{hello world} {a longstring}}
 hello  world
 a      longstring

 % fmtable {{hello world} {a longstring}} 1
 | hello | world      |
 | a     | longstring |

Frederic Bonnet