将命令重命名为不同的名称空间 [英] renaming command into different namespace

查看:98
本文介绍了将命令重命名为不同的名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

使用tcl的rename命令 .

为了使事情尽可能模块化,我想将新功能放入一个单独的命名空间中.

我还想避免将东西添加到toobe增强功能的原始名称空间中.

所以计划是:

  • ::simple::function重命名为::enhanced::simple_function
  • 创建一个新的::simple::function并调用::enhanced::simple_function

这一切工作得很好,除非原始函数在不完全限定其名称的情况下使用其命名空间的其他成员.

这是一个例子:

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,则一切正常. 不幸的是,我无法修复"原始实现.

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

是否可以将我的原始函数重命名为新的命名空间,并允许原始函数中使用不合格的函数名称?

解决方案

关于过程和名称空间的一件事是,用于命令和过程的变量解析的当前名称空间由该过程所使用的名称空间确定放置.这意味着当您将过程rename移至另一个名称空间时,可以更改其行为.当大多数命令位于全局名称空间中时,您通常会避免使用它(因为Tcl在当前名称空间中找不到命令的情况下,这就是Tcl进行搜索的地方),但是它会产生非常深远的影响.可以使代码免受移动的影响(例如,使用完全限定的命令名和namespace upvar而不是variable),但是大多数人都不会打扰,因为这是一个巨大的痛苦,几乎不需要

建议您绝对不要在命名空间之间重命名.这会导致难以调试的麻烦(我可以逐案解释);您所看到的问题就是这种现象的症状,,您不能将我的原始函数重命名为新的命名空间,并允许原始函数中使用不合格的函数名称.

还有其他技术.命令执行跟踪可能适用,就像使用名称空间导入一样.或可能是您正在尝试创建一个伪对象系统:如果是这样,您应该切换到真实的对象系统中,因为它们会处理您未曾想到的许多问题. (我最喜欢的是TclOO,它是Tcl 8.6的一部分,但后来我写了它,所以我有很多偏见!)使用真实的对象系统使切换事情变得非常简单.

To enhance the functionality of a tcl/tk program, I'd like to re-implement one of it's original (namespaced) functions. The new implementation should call the original implementation for the core functionality, and add some nifty stuff around.

This is documented quite well using tcl's rename command.

To keep things as modular as possible, I would like to put my new functionality into a separate namespace.

I would also like to avoid adding things to the original namespace of the toobe-enhanced function.

So the plan was:

  • rename ::simple::function to ::enhanced::simple_function
  • create a new ::simple::function that calls ::enhanced::simple_function

this works all very well, unless the original function uses other members of its namespace without fully qualifying them.

Here's an example:

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"

This gives me:

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

If the original ::foospace::foo uses ::foospace::bar instead of bar, everything works fine. Unfortunately I cannot "fix" the original implementation.

It would also work if i just renamed ::foospace::foo to ::foospace::foo_bar instead of ::barspace::foo but this means touching a namespace that does not belong me (which I would like to avoid).

Is there a way to rename my original function into a new namespace and allow unqualified function names in the original function?

解决方案

One of the things about procedures and namespaces is that the current namespace for the purpose of command and variable resolution for a procedure is determined by the namespace that the procedure is placed in. This means that when you rename the procedure into another namespace, you change how it behaves. You mostly get away with it when the majority of commands are in the global namespace (as that is where Tcl searches if it can't find the commands in the current namespace) but it can have quite a profound effect. It's possible to insulate the code from the effects of being moved around (e.g., using fully-qualified command names and namespace upvar instead of variable) but most people don't bother as it is a colossal pain that is hardly ever needed.

You're recommended to simply never rename things across namespaces. It causes trouble that is hard to debug (I can explain them on a case-by-case basis); the issues you've seen are symptoms of this, and no, you cannot rename my original function into a new namespace and allow unqualified function names in the original function.

There are other techniques. Command execution traces might be suitable, as might using namespace imports. Or it might be that you're trying to do a pseudo-object system: if that's the case, you should switch to one of the real ones as they handle many issues you haven't thought of. (My favourite is TclOO, which ships as part of Tcl 8.6, but then I wrote it so I'm more than a bit biased!) Using a real object system makes switching things around quite a lot simpler.

这篇关于将命令重命名为不同的名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆