isDict

Created by CecilWesterhof.

Default you cannot check if something is a dict, That is why I thought it a good idea to write a proc for it.

A simple check is to check if something is a list and if so if the list contains an even number of elements.

But I find this not good enough, because this would validate:

{[} \] {[} \]

In my opinion this is not a correct dict. (Opinions differ about this.) It can certainly not be created with dict operations. And when doing:

dict set d \{ }

The list is cleaned up and you get:

{[} \] \{ \}

That is why I check if the length of the list is two times the number of the keys. The code becomes:

proc isDict d {
    expr {[string is list $d]
        && !([llength $d] % 2)
        && ((2 * [llength [dict keys $d]]) == [llength $d])
    }
}

isDictKeysValsUnique

I also wanted a proc to check if all keys and values are unique. Keys are unique of-course, but the values should also be unique and no value should also be a key. For this I created the following proc:

proc isDictKeysValsUnique d {
    expr {[isDict $d]
        && [llength [lsort -unique $d]] == [llength $d]
    }
}

PYK 2018-07-24: There's a reason there has never been an example of such on the wiki. This routine would never be needed in a working script because with dict one creates dictionaries guaranteed not to be lists with duplicate values that would be keys, and when consuming key/value pairs, one simply chooses to treate it either as a list of key-value pairs or as a dictionary.

EMJ 2018-07-24: Nor is there any reason, in general, for values to be unique or for values not to happen to have the same value as a key.

CecilWesterhof 2018-07-24: In general not, no. But in my case I had a good reason for that. See Balanced Brackets.


As always: comments, tips and questions are appreciated.

2018-07-22: see also TIP 501 "string is dict".

EMJ 2018-07-22: which I think would also validate the above four-element list.


EMJ 2018-07-22: Put the original four-element list above in a variable and you can use that variable as a dict. Of course the duplicate key disappears because that is a property of dicts (and if the values were different it is the last which would be taken).

Also the proc above will error if fed, for example, a three-element list, so you need a catch or try in there.

CecilWesterhof 2018-07-23: No, it will go OK:

$ set d [list a b c]
a b c
$ isDict $d
0

EMJ 2018-07-23: Ah, yes - lazy evaluation of && .


PYK 2018-07-23: This topic is also discussed at dict tips and tricks. In a nutshell, just ask Tcl:

proc isDict value {
    expr {![catch {dict size $value}]}
}

Often one just wants a script to produce an error if a value is not a dictionary. In this case its sufficient to add this at the right spot, without doing any additional assignment or error production:

dict size $value

Also, opinions don't differ about what is or isn't a correct dictionary. By definition, a list with an even number of elements is dictionary.