Version 0 of My dict with

Updated 2017-05-25 00:33:07 by LarrySmith

I had asked in dict with how to add a key to the dict referred to in the with block. I tried a couple variants but they didn't work. Here's what I came up with (so to speak):

Basically, I wrapped a couple of foreach loops around a script passed to me, one to unpack the existing keys into variable, and the other to repack them. Each loop is quite straightforword. The tricky bit is in addkey, which take the key and the value to set it to, set up access to the original dict variable using the name passed into the script, and then adds the key and the init value onto the end of the dict. It doesn't do any checking to see if you are redeclaring the key. The repack again uses the keys in the dict, which now include the new key(s) added within, so they just get put into the dict.

If you want to avoid cluttering the namespace, you can extend the repack loop with an "unset $key" followed by an "unset dictvar" and everything is nice and tidy.

 proc addkey {key init} {
   upvar dictvar dictname
   uplevel lappend $dictname $key $init
   uplevel set $key $init  
 }

 proc withdict {dictvar script} {
   upvar $dictvar dict
   set template {set dictvar 111
                 puts "dictvar is $dictvar"
                 foreach key [dict keys $111] {set $key [dict get $111 $key]}
                 222
                 foreach key [dict keys $111] {dict set 111 $key [set $key]}
                }
   set script [string map [list 111 $dictvar 222 $script] $template]
   uplevel $script
 }


 set test [dict create a 1 b 2 c 3]

 puts "dict is $test"

 withdict test {
   puts "a=$a, b=$b, c=$c"
   incr a; incr b -1; incr c
   addkey d 5
   incr d -1
   puts "a=$a, b=$b, c=$c, d=$d"
 }

 puts "dict is $test"