Tcl Source Code

View Ticket
Login
Ticket UUID: 1017884
Title: make 'level' arg to uplevel/upvar mandatory
Type: RFE Version: None
Submitter: dvrsn Created on: 2004-08-27 20:58:44
Subsystem: 22. [proc] and [uplevel] Assigned To: msofer
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2020-09-19 17:04:08
Resolution: Wont Fix Closed By: dgp
    Closed on: 2020-09-19 17:04:08
Description:
uplevel always converts its first argument into a
string in order to check if it is the optional ?level?
argument.  If the optional argument is not present, the
first argument is converted anyway, which can take
significant time and loses the benefit of direct list
evaluation.  

set l [list]
for {set c 0} {$c < 10000} {incr c} {
    lappend l 12345
}

proc t1 {l} {
    set cmd [list llength $l]
    uplevel $cmd
}

proc t2 {l} {
    set cmd [list llength $l]
    uplevel 1 $cmd 
}

puts [time {t1 $l} 100]
puts [time {t2 $l} 100]
User Comments: dgp added on 2020-09-19 17:04:08:
Please also note that the list internal rep implementation has been improved in the many years since this ticket was opened.  A canonical list is recognized now even after a string rep is generated.  The cost of string rep generation now lmited to that actual cost of that processing step.  It no longer disables the benefits of direct evaluation of lists without reparsing as scripts.  That makes this issue far far less important, and that has been true for a very very long time now.

pooryorick added on 2020-09-19 15:08:20:

Part of this issue has been fixed in ticket [b9ecf3ce9801c480]: If a single argument is given and that argument is a list containing more than one item, it can not be a level specification, so it is interpreted as the script to evaluate. Morever, no string representation is generated.

The part of this issue that requires a TIP, as discussed in [1017884], remains outstanding.


hobbs added on 2005-05-31 08:53:41:
Logged In: YES 
user_id=72656

Rejecting this request as impractical due to
incompatability.  You can file for a doc clarification, but
you can't just break existing code.

msofer added on 2004-08-28 05:35:00:
Logged In: YES 
user_id=148712

Keeping this as an RFE for making the level argument
mandatory, both for the performance reasons cited here and
to avoid possible confusion.

As a first step, the docs could state that omitting the
'level' argument is deprecated.

msofer added on 2004-08-28 05:30:55:
Logged In: YES 
user_id=148712

dgp later noticed that the docs say that [uplevel 1] is a
syntax error: 
"Level cannot be defaulted if the first command argument
starts with a digit or #."

So: when there is a single argument, its string rep has to
be examined to check that id does not start with a digit or
#. The present behaviour is mandated by the docs.

dgp added on 2004-08-28 04:29:24:
Logged In: YES 
user_id=80530

The docs indicate that

[uplevel 1]

ought to be equivalent to

[uplevel 1 1]

It doesn't appear to be true.
Looks like a bug to me.

Either the docs or the code
needs correcting.

In practical terms. one should
always provide an explicit level
argument to [uplevel] and avoid
any ambiguity or inefficiency.

msofer added on 2004-08-28 04:14:06:
Logged In: YES 
user_id=148712

My first reaction to this is: always specify the level, do
not rely on the default!

My second reaction is: how do you think this could be fixed?
One idea is to assume that, if there is just one argument to
uplevel and it is a pure list, it has to be a script and we
could avoid parsing it. But then the following script would
have a different behaviour:

  % proc 1 {} {puts hi}
  % proc a {} {uplevel [list 1]}
  % a
  wrong # args: should be "uplevel ?level? command ?arg ...?"

So now the question is: is this just a performance bug, or a
real bug? Ie, should that script print "hi" or return an
error as it does now?