I want have a proc which does something if its' argument is a Tcl 8.5 and above dictionary or not. I could not find anything straightforward from Tcl dict command. The code which I could get working is:
proc dict? {dicty} {
expr { [catch { dict info $dicty } ] ? 0 : 1 }
}
Is there anything w/o using catch, something built in?
Thanks.
You can test if a value is a dictionary by seeing if it is a list and if it has an even number of elements; all even length lists may be used as dictionaries (though many are naturally not canonical dictionaries because of things like duplicate keys).
proc is-dict {value} {
return [expr {[string is list $value] && ([llength $value]&1) == 0}]
}
You can peek at the actual type in Tcl 8.6 with tcl::unsupported::representation
but that's not advised because things like literals are converted to dictionaries on the fly. The following is legal, shows what you can do, and shows the limitations (
% set value {b c d e}
b c d e
% tcl::unsupported::representation $value
value is a pure string with a refcount of 4, object pointer at 0x1010072e0, string representation "b c d e"
% dict size $value
2
% tcl::unsupported::representation $value
value is a dict with a refcount of 4, object pointer at 0x1010072e0, internal representation 0x10180fd10:0x0, string representation "b c d e"
% dict set value f g;tcl::unsupported::representation $value
value is a dict with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x10101eb10:0x0, no string representation
% string length $value
11
% tcl::unsupported::representation $value
value is a string with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x100901890:0x0, string representation "b c d e f g"
% dict size $value;tcl::unsupported::representation $value
value is a dict with a refcount of 2, object pointer at 0x1008f00c0, internal representation 0x1008c7510:0x0, string representation "b c d e f g"
As you can see, types are a bit slippery in Tcl (by design) so you're strongly advised to not rely on them at all.