Tcl Source Code

View Ticket
Login
Ticket UUID: 1587442
Title: let upvar only create variables in the current context
Type: RFE Version: None
Submitter: msofer Created on: 2006-10-30 20:05:56
Subsystem: 07. Variables Assigned To: msofer
Priority: 5 Medium Severity:
Status: Open Last Modified: 2006-11-04 02:30:50
Resolution: None Closed By:
    Closed on:
Description:
Currently 
   upvar 1 x ::a::y
will create a variable y in namespace a, linked to the
variable x in the caller's context.

This "action at a distance" is undocumented and
possibly confusing.  It is better IMO to force upvar to
only create variables in the current context (namespace
or proc call frame).

Attached a patch that implements and documents this
feature. Note that the tests var-3.7/8 test for the
current behaviour.
User Comments: dgp added on 2006-11-04 02:30:50:
Logged In: YES 
user_id=80530

I haven't had the cycles to spare
to check this out rigorously, but
it raises my suspicion that it will
thoroughly break things done in the
Tk script library.  Please check that
over carefully before proceeding.

msofer added on 2006-11-03 22:22:06:
Logged In: YES 
user_id=148712

Forgot to mention: [namespace upvar] is in 8.5; it has
nothing to do with this feature request really.

msofer added on 2006-11-03 22:18:19:
Logged In: YES 
user_id=148712

The idea is that you [namespace eval] in the namespace where
you want your variables to be created; I would code your
algorithm as

set tcnt -1
foreach ns {ns1 ns2 ns3} {
    set lst [list namespace upvar [namespace current]]
    for {set cnt 0} {$cnt < 5} {incr cnt} {
        foreach arn {arr lis dic} {
            lappend lst $arn[incr tcnt] $arn$cnt
        }
    }
    namespace eval $ns $lst
}

On the other hand, your current algorithm I would also code
somewhat differently. Note that
  upvar #0 [namespace current]::x ::a::y
is equivalent to the faster (and IMO clearer)
  upvar 0 x ::a::y

So, I would now code yours as

set tcnt -1
set lst [list upvar 0]
foreach ns {ns1 ns2 ns3} {
    for {set cnt 0} {$cnt < 5} {incr cnt} {
        foreach arn {arr lis dic} {
            lappend lst $arn[incr tcnt] ::${ns}::$arn$cnt
        }
    }
}
eval $lst

kaitzschu added on 2006-11-03 19:10:37:
Logged In: YES 
user_id=966098

So how does one do (centralized namespace variable templating without copying)

set tcnt -1
foreach ns {ns1 ns2 ns3} {
 for {set cnt 0} {$cnt < 5} {incr cnt} {
  foreach arn {arr lis dic} {
   upvar #0 [namespace current]::$arn[incr tcnt] ::${ns}::$arn$cnt
  }
 }
}

after this implementation when ns and cnt are variadic? Instead of upvaring these to heavens high one is supposed to

namespace inscope ::$ns upvar [namespace current]::$arn$[incr tcnt] $arn$cnt

or something even remotely resembling? Is this "remotely controlled action at distance" then documented (can I trust these links 
do exist) or am I simply "doing the wrong thing"?

msofer added on 2006-10-31 03:05:56:

File Added - 200677: upvar.patch

Attachments: