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:

That distinction sounds very subtle to me.
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 TCL LOOKUP VARNAME failure, yet the read might still fail if the variable entry refers to a currently unset variable, hence TCL VARNAME READ being the error code.

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?