Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Strange dict behavior part 2

47 views
Skip to first unread message

Bezoar

unread,
Jun 3, 2012, 3:59:25 PM6/3/12
to
Disregard prior post... browser was twitchy.


I was trying a recursive routine to pull out all the keys of a dict and the results differed depending on how I initialized the data in the dict. My results were the same if I accessed the value of a key first then got all the keys vs getting all the keys. A snippet below shows the situation on tcl8.6b2.

==== code ==
proc getType { typestring} {
string range [string range $typestring [string first " a " $typestring ] [string first " with " $typestring ] ] 2 end-1
}
set input [dict create home {} ]
dict set input1 home address { street1 "23 Ave" street2 "Suite 200" }
dict set input home address street1 "6543 Waldorf Plaza"
dict set input home address street2 "Suite 200"

foreach key { home { home address } { home address street1 } { home address street2 } } {
set rep1 [ ::tcl::unsupported::representation [dict get $input1 {*}$key ] ]
set rep [ ::tcl::unsupported::representation [dict get $input {*}$key ] ]
if { [ getType $rep1 ] ne [ getType $rep ] } {
puts "representation for key '$key' in input1 is [ getType $rep1 ] but same key in input is [getType $rep ]"
}

# puts "[format "%50s | %50s" [dict get $input1 {*}$key ] [ dict get $input {*}$key ] ]"
}

If I run the code above I get the following results :
---- output ---
representation for key ' home address ' in input1 is pure string but same key in input is dict
---- end output ----

if I uncoment the last puts statement, I get the following
---- output ---
address { street1 "23 Ave" street2 "Suite 200" } | address {street1 {6543 Waldorf Plaza} street2 {Suite 200}}
street1 "23 Ave" street2 "Suite 200" | street1 {6543 Waldorf Plaza} street2 {Suite 200}
23 Ave | 6543 Waldorf Plaza
Suite 200 | Suite 200

---- end output ----

Why is this? and is it a bug. I would like to get the keys for a dict without knowning the keys in the first place. This seems not to be possible unless you force the user to not use a list to initialize a dict.

Thanks

Carl

Gerald W. Lester

unread,
Jun 3, 2012, 7:08:11 PM6/3/12
to
No bug, I don't see anything wrong with the output.

What were you expecting?????
--
+------------------------------------------------------------------------+
| Gerald W. Lester, President, KNG Consulting LLC |
| Email: Gerald...@kng-consulting.net |
+------------------------------------------------------------------------+

mango

unread,
Jun 3, 2012, 7:46:06 PM6/3/12
to
Look closely at the difference between the commands:

dict set input1 home address { street1 "23 Ave" street2 "Suite 200" }

and

dict set input home address street1 "6543 Waldorf Plaza"

In the first case you have given two keys and asked that the value of the "address" key of the second level be set to { street1 .... }.
In the second case you have given three keys and asked that the value of the "street1" key of the third level be set to "6543 ... ".
These are two different dictionaries as they are nested at different levels.

Also the "dict keys" command will always give you a list of the keys for a dictionary.

Andrew Mangogna

Bezoar

unread,
Jun 4, 2012, 9:32:32 AM6/4/12
to
I expect to get the string " representation for key ' home address ' in input1 is pure string but same key in input is dict" in both cases. But somehow the dict for input1 is changed simply by accessing the dict using get.



Bezoar

unread,
Jun 4, 2012, 9:39:09 AM6/4/12
to
If it is true that these are different dicts then why is this true:
dict get $input1 home address street1 = "23 Ave"
and
dict get $input home address street1 = "6543..."

both access the correct information using the same key list.

And yes you are correct that [dict keys ... ] will give you the keys but I was trying to get all the keys in a dict not just the toplevel ones that the command returns. For example , in the case above the keys or input1 would be :

mango

unread,
Jun 4, 2012, 10:28:04 AM6/4/12
to
In the case of "input1", the value of the "address" key happens to be a value that is of the proper format that the "dict get" command can interpret as a nested dictionary when given a third level of key.

Getting "all the keys" of a dictionary is rather problematic. Since a dictionary value can be any Tcl value, there is no guarantee that there are
any values that are themselves dictionary values below the first level. The fact that some dict commands support traversing nested dictionaries is convenient in many instances but perhaps a bit confusing in this respect. However, if you have some knowledge about the structure of dictionaries that you create in your application, a small proc can do the job. Although, off the top of my head, I'm not sure of the best form in which to return that information.

Gerald W. Lester

unread,
Jun 4, 2012, 11:36:58 AM6/4/12
to
Of course it is. It is converted to a properly quoted list/dictionary when
you access that level.

Donal K. Fellows

unread,
Jun 6, 2012, 9:54:49 AM6/6/12
to
On 04/06/2012 15:28, mango wrote:
> Getting "all the keys" of a dictionary is rather problematic.

Indeed, that's the real problem here. Tcl simply doesn't know that a
value is *meant* to be a dictionary, it just knows whether it has been
accessed as a dictionary before (in which case it can skip re-parsing it
the next time). It also doesn't know anything about the identity of
values; stuff gets shared quite promiscuously, but also duplicated and
converted and generally munged around as necessary. You're not meant to
care too much about the details of that. (With 8.6, you can use
[tcl::unsupported::representation] to poke under the covers but that's
really just a debugging tool that exposes info that you ought to ignore.)

If you know externally that you have a 3-level dictionary (or some other
structure) it's trivial to enumerate the leaf key paths. That's the real
Tcl way.

Donal.
0 new messages