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

Strange behaviour of [dict exists]

56 views
Skip to first unread message

Alan Grunwald

unread,
Jul 28, 2022, 5:37:42 PM7/28/22
to
I've spent several not-so-happy hours today searching for a bug caused
by someone doing

[dict exists foo garp]

instead of

[dict exists $foo garp]

I'm surprised that the former code works since, for example [dict get
foo] and [dict size foo] throw an exception if you miss out the dollar
sign. Is this a bug? If not, what benefit does this anomalous behaviour
of [dict exists] bring with it?

Thanks.

Steve Bennett

unread,
Jul 28, 2022, 6:04:24 PM7/28/22
to
% dict exists foo garp
missing value to go with key

Maybe you inadvertently caught the exception

Christian Gollwitzer

unread,
Jul 28, 2022, 6:33:57 PM7/28/22
to
Am 29.07.22 um 00:04 schrieb Steve Bennett:
> % dict exists foo garp
> missing value to go with key
>
> Maybe you inadvertently caught the exception
>

(chris) 50 % info patchlevel
8.6.9
(chris) 51 % dict exists foo garp
0


What is your patchlevel?

Christian

apn

unread,
Jul 28, 2022, 8:57:33 PM7/28/22
to
See https://core.tcl-lang.org/tcl/tktview/3598385fffffffffffff for the
discussion on this. fwiw

Rich

unread,
Jul 28, 2022, 10:27:28 PM7/28/22
to
Steve Bennett <ste...@workware.net.au> wrote:
> On Friday, July 29, 2022 at 7:37:42 AM UTC+10, Alan Grunwald wrote:
>> I've spent several not-so-happy hours today searching for a bug caused
>> by someone doing
>>
>> [dict exists foo garp]
>>
>> instead of
>>
>> [dict exists $foo garp]
>>
>> I'm surprised that the former code works since, for example [dict get
>> foo] and [dict size foo] throw an exception if you miss out the dollar
>> sign. Is this a bug? If not, what benefit does this anomalous behaviour
>> of [dict exists] bring with it?
>>
>> Thanks.
>
> % dict exists foo garp
> missing value to go with key
>
> Maybe you inadvertently caught the exception

On 8.6.11 I get what the OP reported:

$ rlwrap tclsh
% set tcl_patchLevel
8.6.11
% dict exists foo garp
0
%

Steve Bennett

unread,
Jul 29, 2022, 3:59:09 AM7/29/22
to
Fair enough. IMHO they broke it.
Jim Tcl is staying with the old way. What the OP reports is definitely a common scenario.

Alan Grunwald

unread,
Jul 29, 2022, 7:01:01 AM7/29/22
to
Thanks for pointing me at the ticket(s).

To attempt to answer my second question, the benefit appears to come
with nested dictionaries. The current implementation allows you to
wander around such dictionaries when you don't know how deeply nested it is.

I think that's going to be helpful less often than people forgetting the
dollar sign, but YMMV.

May I take some hope from the fact that the resolution is "Wont fix"
rather than something like "Not a bug"?

For my money the solution would be for [dict exists] to throw an error
and there to be a [string is dict] command, as suggested by mistachkin
on 2012-12-27 in a comment on the ticket.

FWIW I also agree completely with Donal that thrashing backward and
forward is unhelpful.

heinrichmartin

unread,
Jul 29, 2022, 7:45:47 AM7/29/22
to
On Friday, July 29, 2022 at 1:01:01 PM UTC+2, Alan Grunwald wrote:
> May I take some hope from the fact that the resolution is "Wont fix"
> rather than something like "Not a bug"?
>
> For my money the solution would be for [dict exists] to throw an error
> and there to be a [string is dict] command, as suggested by mistachkin
> on 2012-12-27 in a comment on the ticket.
>
> FWIW I also agree completely with Donal that thrashing backward and
> forward is unhelpful.

Let me second all that. Throwing an error for invalid data is consistent.
Imho, https://core.tcl-lang.org/tcl/info/3475264 should have been a TIP (and should probably have been declined).

"[...] sort out between yourselves what it should be and I'll willingly make it work that way if it doesn't already. Until then, this issue stays closed."

Independent reporters found this regression in 2012, 2018, and 2022 along with many supporters and hardly anyone opposing; is this representative?
Without any hidden meaning: what is the expected process (medium and decision criteria) to continue?

> > On 7/29/2022 3:07 AM, Alan Grunwald wrote:
> >> I've spent several not-so-happy hours today searching for a bug caused
> >> by someone doing
> >>
> >> [dict exists foo garp]
> >>
> >> instead of
> >>
> >> [dict exists $foo garp]
> >>

We have very basic code checkers in place to fail fast. "Basic" refers to "not a full Tcl parser". I cannot paste the full file, but basically I am using regular expressions with sed.

...
# regexp of suspicious code
# \x24 ... $ (prevent a match in this file known_pitfalls.tcl)
# \x61 ... a (prevent a match in this file known_pitfalls.tcl)
# \< ... beginning of a word
# \> ... end of a word
set forbidden {
# for variable names true and false use ${true} and ${false} respectively
{\x24false\>\|\x24true\>}
# use return "result" if you really mean it
{\<return \+result\>}
# very common spelling mistakes
{\<\x61dress\>}
{\<\(Res\|res\|S\|s\)etted\>}
# string's subcommand concat does not exist in Tcl, was string cat intended?
{\<string \+concat }
# these procedures use variable names (override with ${name})
{\<dict \+\(set\|incr\|append\|lappend\|unset\|update\|with\) \+\$\(\w\|:\)\+}
{\<\(set\|incr\|append\|lappend\|unset\|vwait\|lset\|info \+exists\|info \+vars\) \+\$\(\w\|:\)\+}
{::struct::set \+\(include\|exclude\|add\|subtract\) \+\$\(\w\|:\)\+}
# these procedures take values (use braces)
{\<dict \+\(get\|exists\|filter\|info\|keys\|merge\|remove\|replace\|size\|values\) \+[^\$\{\[ ][^ ]*}
{\<\(lreplace\|lassign\|lindex\|linsert\|llength\|lrange\|lreplace\|lreverse\) \+[^\$\{\[ ][^ ]*}
{::struct::set \+\(empty\|size\|contains\|union\|difference\|symdiff\|intersect3\) \+[^\$\{\[ ][^ ]*}
# always use the optional argument level, default is 1
{\<up\(var\|level\) \+[^$#0-9\\]}
}
...
# erase commented lines in data
set forbidden [join [regsub -all -line {^\s*#.*$} $forbidden {}] {\|}]
set deprecated [join [regsub -all -line {^\s*#.*$} $deprecated {}] {\|}]
set sed [format {
# find suspicious code in single line
s/^ *\([0-9]\+\)\t.*\(%s\).*$/\1: suspicious looking code {\2}/p;t
# if not suspicious, check for deprecated procs
s/^ *\([0-9]\+\)\t\(\|.*;\|.*\[\|.*%s\) *\(%s\) .*$/\1: DEPRECATED proc {\3}/p;t
# if not deprecated, check with the previous line (in hold buffer)
H;x
# indentation when closing nested blocks
s/^ *\([0-9]\+\)\t\( *\}\)\n *\([0-9]\+\)\t\2/\1-\3: suspicious looking code {equal indentation at end of block}/p;t
} $forbidden \{ $deprecated]
...
# - print line numbers
set result [split [exec cat -n $argv | sed -n $sed] \n]
...

Maybe that helps someone :-)
0 new messages