VI 2015-10-23 : I have deeply nested structures built with dicts, and it makes for very descriptive code. I have often been inconvenienced by some dict commands only applying to the first level of keys. Examples are dict create, dict append, dict lappend, dict incr, dict update. So I implemented one of these commands (incr). The p in dict-pincr stands for path.
e.g. I would like this script:
dict set a b c d m wi 0 dict-pincr a {b c d m wi} puts $a
to print:
b {c {d {m {wi 1}}}}
This works. but could be improved. I used the empty variable name {} to reduce the chance of a conflict, but I think this should be possible without upvar.
proc dict-pincr {dictname keypath} { set keylen [llength $keypath] if {$keylen < 1} { error "Need at least one key name" } elseif {$keylen == 1} { uplevel 1 [list dict incr $dictname [lindex $keypath 0]] } else { upvar $dictname {} dict with {} { dict-pincr [lindex $keypath 0] [lrange $keypath 1 end] } return [set {}] } }
lappend:
proc dict-plappend {dictname keypath args} { set keylen [llength $keypath] if {$keylen < 1} { error "Need at least one key name" } elseif {$keylen == 1} { uplevel 1 [list dict lappend $dictname [lindex $keypath 0] {*}$args] } else { upvar $dictname {} dict with {} { dict-plappend [lindex $keypath 0] [lrange $keypath 1 end] {*}$args } return [set {}] } } dict set a b c d m wi 0 dict-plappend a {b c d m wi} 1 2 3 4 puts $a
gives
b {c {d {m {wi {0 1 2 3 4}}}}}