将命令重命名为不同的命名空间

renaming command into different namespace

为了增强 tcl/tk 程序的功能,我想重新实现其中一个原始(命名空间)功能。新的实现应该调用核心功能的原始实现,并添加一些漂亮的东西。

这被很好地记录了 using tcl's rename command

为了尽可能保持模块化,我想将我的新功能放入一个单独的命名空间中。

我也想避免在 toobe 增强功能的原始命名空间中添加东西。

所以计划是:

这一切都很好,除非原始函数使用其名称空间的其他成员而没有完全限定它们。

这是一个例子:

namespace eval ::foospace:: {
   proc bar {a} { puts $a }
   proc foo {X} { bar "foospace:foo:: $X" }
}
## test original function
::foospace::foo "hello world"

## shadowing the original ::foospace::foo into a new namespace
rename ::foospace::foo ::barspace::foo
proc foospace::foo {x} {
  puts "DEBUG: $x"
  ::barspace::foo "$x"
}
# test enhanced function
::foospace::foo "goodbye moon"

这给了我:

invalid command name "bar"
    while executing
"bar "foospace:foo:: $X" "

如果原来的 ::foospace::foo 使用 ::foospace::bar 而不是 bar,则一切正常。 不幸的是我不能 "fix" 原来的实现。

如果我只是将 ::foospace::foo 重命名为 ::foospace::foo_bar 而不是 ::barspace::foo 也会起作用,但这意味着要触及不属于 的名称空间 我(我想避免)。

有没有办法将我的原始函数重命名为新的命名空间并允许在原始函数中使用非限定函数名称?

关于过程和命名空间的一件事是,用于过程的命令和变量解析的当前命名空间由放置该过程的命名空间决定。这意味着当您 rename 过程到另一个命名空间,你改变它的行为方式。当大多数命令都在全局命名空间中时(因为如果在当前命名空间中找不到命令,Tcl 会在此处搜索),您通常可以摆脱它,但它会产生相当深远的影响。可以使代码免受四处移动的影响(例如,使用完全限定的命令名称和 namespace upvar 而不是 variable),但大多数人不会打扰,因为这是一个巨大的痛苦几乎不需要。

建议您永远不要跨命名空间重命名。它会导致难以调试的麻烦(我可以根据具体情况进行解释);您看到的问题是这种情况的症状,不,不能将我的原始函数重命名为新的命名空间并允许不合格的函数名称原始函数。

还有其他技巧。命令执行跟踪可能是合适的,就像使用命名空间导入一样。或者可能是您正在尝试做一个伪对象系统:如果是这种情况,您应该切换到一个真实的系统,因为它们可以处理 many 您没有处理的问题想到。 (我最喜欢的是 TclOO,它作为 Tcl 8.6 的一部分发布,但后来我写了它,所以我有点偏见!)使用真实的对象系统使得切换事情变得非常简单。