TCL命名空间中的变量

发布于 2025-01-07 09:43:30 字数 324 浏览 0 评论 0原文

我有一个关于 TCL 命名空间中的变量的问题。

我有两个.tcl文件,a.tcl,b.tcl,我在这两个文件中定义相同的全局变量,例如:

a.tcl

variable same "hello1"

b.tcl

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

,但在b.tcl中,我尝试定义一个proc来使用变量“same”,是否存在冲突? proc use() 中使用的是哪一个?

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()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苦妄 2025-01-14 09:43:30

从您的问题(以及对 Donal 的评论)看来,您认为文件与名称空间有关。这种想法是不正确的。

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
    }
}

这个故事的寓意是代码所在的文件与命名空间或其他任何东西无关。对于位于单独命名空间中的命令或变量,必须将其显式放置在其中。

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.

谁许谁一生繁华 2025-01-14 09:43:30

use 过程将与 same 变量位于相同的命名空间中(代码所在的文件与其创建命令和变量的命名空间 100% 正交)。 但是use 的主体默认情况下无法访问命名空间的变量,因为默认情况下所有过程声明的变量都是局部变量。这意味着要访问 same,您应该将其带入 variable 的范围,可能不带值初始化参数:

proc use {} {
    variable same
    puts $same
}

您还可以使用完全限定名称直接变量,但这往往会更慢(尤其是在循环中)。


在你问之前,我希望上面的代码会导致use打印“hello1”或“hello2”,具体取决于a.tcl和b.tcl的顺序是来源d。任何命名空间都必须通过命名空间 eval ::someNsName { ...script... } 显式完成。您可能会将这样的内容放在每个脚本文件的其余内容中。编写过度依赖源文件顺序的代码通常被认为是不好的形式,主要是因为它往往更难以调试......

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…

苍暮颜 2025-01-14 09:43:30

暂时忘记这两个文件。假设您只有一个文件,内容为:

variable x hello ;# this is a global variable.

proc use {} {
  puts $x
}

这应该会导致一个错误,提示诸如 $x 未定义之类的内容。为什么?因为 Tcl 与 C 不同,不会将任何您不要求的内容导入到函数中。让我再说一遍:tcl procs 不会看到您不告诉它看到的全局或命名空间变量。

因此,要导入全局变量,传统方法是使用 global 命令:

variable x hello

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

这应该可行。

当然,对于命名空间,global 这个词没有意义,因此创建 variable 命令是为了允许命名空间中定义的进程查看命名空间变量:

namespace eval foo {
  variable x hello

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

还有另一种方法导入全局和命名空间变量,无需显式使用 globalvariable:只需指定完整的命名空间。全局命名空间只是 :: 因此以下内容也有效:

variable x hello

proc use {} {
  puts $::x
}

当然:

namespace eval foo {
  variable x hello

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

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
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文