renaming command into different namespace

时间秒杀一切 提交于 2019-12-11 19:42:49

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/33847898/renaming-command-into-different-namespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!