user707549
user707549

Reputation:

The variable in namespace of TCL

I have a question about variables in namespace of TCL.

I have two .tcl files, a.tcl, b.tcl, I define the same global variable in these two files, for example:

a.tcl

variable same "hello1"

b.tcl

variable same "hello2"
proc use {} {
   puts same
}

but in b.tcl, I try to define a proc to use the variable "same", is it a conflicts? which same is used in proc use()?

Upvotes: 2

Views: 10211

Answers (3)

slebetman
slebetman

Reputation: 113876

Forget about the two files for a moment. Lets assume you just have a single file and the content is:

variable x hello ;# this is a global variable.

proc use {} {
  puts $x
}

This should result in an error that says something like $x is undefined. Why? Because Tcl, unlike C, doesn't import anything into a function that you don't ask it to. Let me say that again: tcl procs doesn't see global or namespace variables that you don't tell it to see.

So, to import global variables the traditional way is to use the global command:

variable x hello

proc use {} {
  global x ;# import $x into this proc
  puts $x
}

this should work.

With namespaces of course the word global doesn't make sense so the variable command was created to allow procs defined in a namespace to see namespaced variables:

namespace eval foo {
  variable x hello

  proc use {} {
    variable x ;# import $x into this proc
    puts $x
  }
}

There is also another way to import global and namespaced variables without explicitly using either global or variable: just specify the full namespace. The global namespace is simply :: so the following also works:

variable x hello

proc use {} {
  puts $::x
}

and of course:

namespace eval foo {
  variable x hello

  proc use {} {
    puts $foo::x
  }
}

Upvotes: 1

RHSeeger
RHSeeger

Reputation: 16262

It appears from your question (and comments to Donal) that you believe that files have anything to do with namespaces. This thought is incorrect.

a.tcl

variable same "hello a" ;# global namespace

b.tcl

variable same "hello b" ;# global namespace
proc use {} {
    variable same ;# reads from the global namespace
    puts $same    ;# will puts "hello a" or "hello b" depending on whether
                  ;# a.tcl is sourced after b.tcl or not
}

c.tcl

namespace eval ::not_the_global {
    variable same "hello c" ;# a different namespace, and a different variable than
                            ;# the one from the previous two files
}

d.tcl

namespace eval ::not_the_global {
    proc use {} {     ;# a different use proc from the one in b.tcl
        variable same ;# the variable defined in this namespace in c.tcl
        puts $same    ;# will output "hello c" no matter is a.tcl or b.tcl 
                      ;# were sourced
    }
}

The moral of the story being that the file that code is in is irrelevant, to namespaces or anything else. For a command or variable to be in a separate namespace, it must explicitly be placed in there.

Upvotes: 4

Donal Fellows
Donal Fellows

Reputation: 137557

The use procedure will be in the same namespace as the same variable (which file the code is in is 100% orthogonal to which namespace it creates commands and variables in). However, the body of use will not have access to the variables of the namespace by default because all procedure-declared variables are local variables by default. This means that to get access to same, you should bring it into scope with variable, probably without the value-initialization argument:

proc use {} {
    variable same
    puts $same
}

You could also use the fully-qualified name of the variable directly, but that tends to be slower (especially in a loop).


Before you ask, I'd expect the above code to cause use to print either “hello1” or “hello2”, depending on which order a.tcl and b.tcl are sourced. Any namespacing has to be done explicitly through a namespace eval ::someNsName { ...script... }. You'd probably put such a thing around the rest of the contents of each of your script files. It's usually considered bad form to write code that depends excessively on the order you source files, mostly because it tends to be quite a lot more difficult to debug…

Upvotes: 3

Related Questions