namespacestcl

Tcl variable interact in different namespace, how to fix


In tcl, I need to source some files, file1, file2, file3,.... fileN, I create each namespace for each file, but the var set in each namespace will impact other namespace's var

below is my code:

proc source_file { args } {
global i 
  namespace eval NC{$i} {
   uplevel #0 [list source [uplevel 1 {set args}]]
  }
 incr i
}
set i 1
set A 123
source_file file1.tcl
source_file file2.tcl

file1.tcl:

set A 456;
puts $A

file2.tcl:

puts $A 

I expect file2.tcl's puts will print 123, but it print 456, what's my code error?


Solution

  • uplevel #0 is almost the same as doing namespace eval ::; the code argument runs in the global namespace. (The difference is in how they manage the stack; most code won't care about that difference.) That means both files are running in the same namespace, the global one.

    In Tcl 8, you would need the file to properly say:

    variable A 456
    puts $A
    

    To get the variable to be in the right namespace, and you need to invoke the file with:

    uplevel "#0" [list namespace eval $ns [list source $filename]]
    # I put #0 in quotes just to defeat the syntax highlighter here
    

    assuming you put the namespace and filename in the right local variables, of course.


    In Tcl 9, resolution is tweaked. That will break this code more and in several places, but in ways that should fix more bugs than it makes...