From: DaveOz on 31 May 2010 11:21 Hello, I encountered a behavior of dict exists which I thought seemed unexpected. I'm relatively new to TCL so apologies if I'm missing something obvious or going over old ground .. Can anyone confirm that this is indeed TCL working as designed? I have a dictionary which is sometimes nested, sometimes not. So I need to test whether a value in the nested dict is there before attempting to do a dict get. eg. > set dict [dict create a [dict create c 3] b 2] a {c 3} b 2 > dict exists $dict a c 1 All good.. but when the nested dict is not there, I get an error doing the same test: > dict set dict a 1 a 1 b 2 > dict exists $dict a c missing value to go with key I would have liked this just to return a 0 instead of an error, but as it stands, to check if the nested value exists and avoid the possibility of an error I need to something along the lines of: > if { [dict exists $dict a] && [llength [dict get $dict a] > 1] && [dict exists $dict a c] } { ..... } Seems a bit cumbersome.. how do most folk get round this? > info patchlevel 8.5.8
From: MartinLemburg on 31 May 2010 11:53 Hi Dave, "dict exists" tries to convert the data to test the existence of a key on into a dictionary! So ... dict exists [dict create a 1 b 2] a c .... will first try to do ... dict get {a 1 b 2} a c .... which is the same like ... dict get [dict get {a 1 b 2} a] c .... which is the same like ... dict get 1 c .... which causes the error: "missing value to go with key" "dict exists" only works on real dictionaries or lists with an even count of elements. So it is not the right thing to test for a nested dictionary! Something like the following code could be used to test, if data is usable as dictionary: proc stringIsDict {string} { # loosely tested an empty string is a dictionary # if {$string eq ""} { return 1; } # parsable as list, than parsable as dict # if {![string is list $string]} { return -code ok -errorcode [list EINVAL "not parsable as list or dict"] 0; } # an even count of elements used as pairs of key and value # if {[llength $string] % 2 != 0} { return -code ok -errorcode [list EINVAL "no even count of elements to represent key-value-pairs"] 0; } # unique keys # set keys [list]; foreach {key value} $string { if {$key in $keys} { return -code ok -errorcode [list EINVAL "duplicate key \"$key\" found"] 0; } lappend keys $key; } return 1; } After applying "stringIsDict" you could access the data/string as dictionary. Best regards, Martin On 31 Mai, 17:21, DaveOz <daveo...(a)gmail.com> wrote: > Hello, > I encountered a behavior of dict exists which I thought seemed > unexpected. I'm relatively new to TCL so apologies if I'm missing > something obvious or going over old ground > . > Can anyone confirm that this is indeed TCL working as designed? > > I have a dictionary which is sometimes nested, sometimes not. So I > need to test whether a value in the nested dict is there before > attempting to do a dict get. > > eg. > > > set dict [dict create a [dict create c 3] b 2] > a {c 3} b 2 > > dict exists $dict a c > > 1 > > All good.. but when the nested dict is not there, I get an error doing > the same test: > > > dict set dict a 1 > a 1 b 2 > > dict exists $dict a c > > missing value to go with key > > I would have liked this just to return a 0 instead of an error, but as > it stands, to check if the nested value exists and avoid the > possibility of an error I need to something along the lines of: > > > if { [dict exists $dict a] && [llength [dict get $dict a] > 1] && [dict exists $dict a c] } { > .... > } > > Seems a bit cumbersome.. how do most folk get round this? > > > info patchlevel > > 8.5.8
From: DaveOz on 1 Jun 2010 05:01 Thanks very much for your help Martin and the code snippet. I see why dict exists acts the way it does from the example you gave. I guess I was making assumptions from the description of it: "[dict exists] returns a boolean value indicating whether the given key (or path of keys through a set of nested dictionaries) exists in the given dictionary value. This returns a true value exactly when dict get on that path will succeed. " When it says it will return a true value exactly when dict get succeeds, I made the mistake of assuming the converse would also be true: i.e. it will return false exactly when dict get would fail for the path in question. Hypothetically, would that not seem like more consistent behavior?
From: MartinLemburg on 1 Jun 2010 06:20 > Hypothetically, would that not seem like more consistent behavior? Yes! I would even assume, that "dict exists" on an invalid dict should return 0 or an appropriate error message, which would not be the same, than that from "dict get". Best regards, Martin On 1 Jun., 11:01, DaveOz <daveo...(a)gmail.com> wrote: > Thanks very much for your help Martin and the code snippet. > I see why dict exists acts the way it does from the example you gave. > > I guess I was making assumptions from the description of it: > > "[dict exists] returns a boolean value indicating whether the given > key (or path of keys through a set of nested dictionaries) exists in > the given dictionary value. This returns a true value exactly when > dict get on that path will succeed. " > > When it says it will return a true value exactly when dict get > succeeds, I made the mistake of assuming the converse would also be > true: i.e. it will return false exactly when dict get would fail for > the path in question. Hypothetically, would that not seem like more > consistent behavior?
|
Pages: 1 Prev: How to learn tcltest package Next: Tcl_NewListObj returns no data |