Associative Arrays in Tcl
A Tcl array is a variable that holds a collection of key-value pairs rather than a single scalar value -- you create one implicitly by assigning to an indexed name like set scores(Alice) 90, or in bulk with array set scores {Alice 90 Bob 85 Carol 92}. Unlike lists or scalars, an array is not itself a value you can pass around; it's a special kind of variable, and each name(key) reference is really addressing one element of that variable's underlying hash table. This makes arrays a natural fit for lookup tables and named collections of related data, similar to associative arrays or hash maps in other languages.
Cricket analogy: set scores(Kohli) 82 mirrors a scorekeeper's tally sheet where each player's name is the lookup key and their run total is the stored value -- you look up 'Kohli' directly instead of scanning through an ordered list of all scores to find his.
Working with Arrays
array names scores returns a list of every key currently in the array, in unspecified order unless you sort it, array get scores returns a flat key-value list suitable for feeding back into array set elsewhere, and array size scores reports how many elements it holds. To visit every entry, combine array names with foreach: foreach key [array names scores] {puts "$key: $scores($key)"}. array exists scores checks whether a variable is an array at all, and array unset scores clears it, both useful for defensive checks before operating on a possibly-undefined array.
Cricket analogy: foreach key [array names scores] {puts "$key: $scores($key)"} printing every player's score mirrors reading out a full scorecard name by name, while array exists scores checking before use mirrors a scorer verifying the scoresheet actually exists before trying to read from it.
Introducing dict
dict is Tcl's more modern, ordered key-value structure, and critically it's a value, an ordinary string with a well-defined internal representation, not a special variable type like an array. dict create k1 v1 k2 v2 builds a new dict, dict set d key value returns an updated dict with that key set (or updates a dict-valued variable in place when given a variable name), and dict get $d key retrieves a value, raising an error if the key is absent. Because dicts can hold other dicts as values, they naturally represent nested/structured data like JSON-style configuration, whereas plain arrays cannot directly nest.
Cricket analogy: dict create name Kohli team India runs 82 building a structured player record mirrors a modern digital scorecard app storing a player's full profile as one nested object, and dict get $player team retrieving just the team field mirrors tapping on a player's card to see one specific stat.
Choosing Between array and dict
The core distinction is that an array is a variable, you can't pass 'the array' as a single argument to a procedure without upvar or array get/array set round-tripping, while a dict is a value that can be stored in a scalar variable, passed to a procedure, returned from a function, or nested inside a list or another dict, just like any string or number. For simple flat lookup tables inside a single scope, arrays remain idiomatic and are marginally faster for repeated single-key access; for anything that needs to be passed around, nested, or returned from a procedure, dict is almost always the better choice in modern Tcl (8.5+).
Cricket analogy: Passing a dict of match stats to proc summarize {stats} {...} is like handing a fully compiled scorecard printout to a commentator, a self-contained value they can read from directly, whereas an array is more like the live scoreboard itself, which you can't hand someone; you'd have to give them upvar access to it.
# Array: flat key-value lookup table
array set scores {Kohli 82 Rohit 45 Bumrah 3}
foreach player [array names scores] {
puts "$player: $scores($player)"
}
# Dict: nested, portable value
set player [dict create name Kohli team India stats {runs 82 balls 49}]
puts [dict get $player team]
puts [dict get $player stats runs]
proc summarize {playerDict} {
return "[dict get $playerDict name] scored [dict get $playerDict stats runs] runs"
}
puts [summarize $player]Because a dict is an ordinary string value, it preserves insertion order when you iterate it with dict for {key value} $d {...}, unlike a plain array whose array names order is unspecified (implementation-defined by the underlying hash table) unless you explicitly sort the returned list.
An array cannot be passed to a procedure as a single argument the way a dict can -- proc show {arr} {puts $arr(key)} will not work as expected because arr inside the proc is just a scalar copy of whatever string was passed, not a reference to the caller's array. To operate on a caller's array inside a procedure, you must use upvar 1 arrName localName, or convert it with array get/array set at the boundary. Dicts avoid this problem entirely because they're regular values.
- A Tcl array is a variable holding key-value pairs, created via set arr(key) value or array set arr {...}.
- array names, array get, array size, array exists, and array unset are the core commands for inspecting and managing arrays.
- dict is an ordered key-value value type, an ordinary string, not a special variable, built with dict create and read with dict get.
- Dicts can nest other dicts as values, naturally representing structured/hierarchical data; plain arrays cannot nest directly.
- Because arrays are variables, passing one into a procedure requires upvar or round-tripping through array get/array set.
- Dicts, being values, can be passed to and returned from procedures, stored in variables, and nested inside lists or other dicts freely.
- For simple flat lookup tables in one scope, arrays are idiomatic; for anything passed around or nested, prefer dict.
Practice what you learned
1. Why can't you pass a Tcl array directly as a single argument to a procedure the way you can a dict?
2. What is the main structural advantage of dict over a plain array for representing configuration data?
3. What does array names scores return?
4. How does dict for {key value} $d {...} differ from iterating array names with a foreach?
Was this page helpful?
You May Also Like
Procedures in Tcl
Learn how to define reusable commands with proc, including default arguments, variable-arity args, return values, scope, and recursion.
String Manipulation in Tcl
Explore Tcl's string command ensemble for measuring, searching, matching, formatting, and building strings.
Loops in Tcl
Master Tcl's while, for, and foreach loops, along with break and continue for controlling repeated execution.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics