Tcl Source Code

View Ticket
Login
Ticket UUID: 8e91ec4866db095f1d90d4e2fd468305a8a80bf8
Title: {TCL LOOKUP VARNAME} vs {TCL READ VARNAME}
Type: Bug Version: 8.6
Submitter: aspect Created on: 2015-07-23 05:29:56
Subsystem: 07. Variables Assigned To: dkf
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2015-08-02 16:48:44
Resolution: Rejected Closed By: dkf
    Closed on: 2015-08-02 16:48:44
Description:
I don't know what category to put this in - was hoping for something like "Exceptions".

{TCL READ VARNAME} seems like a mistake - {TCL LOOKUP VARNAME} occurs more
frequently in the source, and it is not clear to the script writer why one
might trap one but not the other:

% unset a
% try {puts $a} on error {e o} {puts [dict get $o -errorcode]}
TCL LOOKUP VARNAME a
% apply {{} {try {puts $a} on error {e o} {puts [dict get $o -errorcode]}}}
TCL READ VARNAME
% try {apply {{} {puts $a}}} on error {e o} {puts [dict get $o -errorcode]}
TCL READ VARNAME
% try {puts $a(a)} on error {e o} {puts [dict get $o -errorcode]}
TCL LOOKUP VARNAME a
% array set a {}
% try {puts $a(a)} on error {e o} {puts [dict get $o -errorcode]}
TCL READ VARNAME

Despite frequency of occurrence, READ seems to only be emitted from one location in
the source:

http://core.tcl.tk/tcl/artifact/0a01b4037e1d4eec?ln=1414

Where it has been since:

http://core.tcl.tk/tcl/info/a12728cbb91807a8

While the test suite is mostly quite thorough with errors, it only touches
{TCL * VARNAME} by accident, in cmdAH-23.6.  The above examples seem like a good
start for test cases, but I'm not sure what others should exist.
User Comments: dkf added on 2015-08-02 16:48:44: (text/html)
<blockquote><i>That distinction sounds very subtle to me.</i></blockquote>
Yes, but that's how it is internally. When you put code into a procedure (well, anything with a Local Variable Table defined) you change how variables are located; simple variable references become a lot more efficient, and the lookup of them no longer fails ever, so no <tt>TCL LOOKUP VARNAME</tt> failure, yet the read might still fail if the variable entry refers to a currently unset variable, hence <tt>TCL VARNAME READ</tt> being the error code.
<p>
In short, Tcl does not guarantee to give exactly the same reason for failing in all cases where it generates a failure, even if those cases are superficially similar; those cases may be actually looking very different from Tcl's own internal perspective. I don't propose to alter anything, or document that this variation occurs. We might change it all without warning (but probably won't; we're lazy too!)

aspect added on 2015-07-24 02:51:38:
That distinction sounds very subtle to me.  Var structures aren't
something I'm familiar with from the script level, and I'm not sure
I should be!  It has struck me a few times, and anecdotally I have
record of evilotto questioning the array behaviour on chat months 
ago.

For the array cases I can sort of understand (LOOKUP if the array
doesn't exist; READ if the element doesn't), but the difference
between the first two cases isn't obvious.  Is this interpreted vs
bytecode paths?

I don't see that the distinction aids the programmer to write
correct code.  Both produce exactly the same error message, giving
no hint that the difference exists, and when I want to trap one I
practically always want to trap both, which requires two independent
trap clauses and code duplication.  I think they should at least
share a common prefix to facilitate this common case.

Perhaps {TCL VARNAME READ} would have been a better structure, but I
think that horse has bolted.  Perhaps we can salvage something in
the form of {TCL LOOKUP VARNAME $varName $op} but that's starting to
look pretty cumbersome.  {TCL LOOKUP VARNAME ?varName?} across the
board seems pretty appealing to me right now.

I could be convinced that it's useful to have distinct READ and
LOOKUP error codes, but that moves the focus on to documentation.
And this sounds like a right pain to explain to impatient novice
programmers -- enough that I'd rather mess with code than prose ;-).

dgp added on 2015-07-23 22:10:33:
The LOOKUP code indicates something went wrong trying
to map the variable name to a Var struct.

The READ code indicates a Var struct was found without
any trouble, but then it didn't hold any value.

aku added on 2015-07-23 17:53:32:
dgp - I actually don't. Is this documented somewhere ? (Manpage ?)

dgp added on 2015-07-23 14:13:48:
It does seem strange that the TCL READ VARNAME code fails
to report the name of the variable that lacks a value.

dgp added on 2015-07-23 14:09:54:
You understand the distinction being made by the two
-errorcode values, right?