Tcl如何从导入的例程中确定导入器的名称空间
我正在试图在Tcl 8.4.18中实现一个简单的面向对象的系统来摔跤。我看过Itcl,stooops,XOTtcl等等,还没有决定是否要使用它们,特别是如果我可以用另一种简单的方法做到这一点。无论如何,让我们说,我有一个命名空间Tcl如何从导入的例程中确定导入器的名称空间
namespace eval Object {
namespace export setvar
proc setvar { model name value } {
set ${model}::${name} $value
}
}
,然后我用另一个名字空间
namespace eval Model {
namespace import ::Object::*
variable foo 0
}
我可以设置变量这样
Model::setvar Model foo 2
puts $Model::foo
,输出“2,如果“继承” ”。但是,我想简化代码,以便Object命名空间中的例程“setvar”可以确定它是从“Model”命名空间中调用的。事情是这样的:
proc setvar { name value } {
set myspace [namespace current]
set ${namespace}::${name} $value
}
,然后调用它像
Model::setvar foo 2
但是,这并不工作,因为[命名空间电流]返回“:对象”,而不是“::模型”。根据文档,这是因为输入只是引用回Object对象命名空间。
使用例程setvar的原因是尝试和实现一个变量覆盖,以便我可以在模型中使用foo(如果存在),否则从Object中获取它。
有没有其他方法可以做到这一点?或者我应该只使用其他工具之一?
感谢
你正在寻找的代码是棘手,但是可以做到(关键是namespace which
):
proc setvar { name value } {
set cmdnameScript [list namespace which [lindex [info level 0] 0]]
set myspace [namespace qualifiers [uplevel 1 $cmdnameScript]]]
set ${myspace}::${name} $value
}
如果你使用8.5(或更高版本),可以考虑与更换,去年set
:
namespace upvar $myspace $name var
set var $value
这是一个更容易与一旦事情开始变得复杂的工作。如果做不到这一点,确实使用upvar
(几乎一样易于使用,没有那么快,便携追溯到Tcl的8.0):
upvar 0 ${myspace}::$name var
set var $value
(FWIW,我在8.4.7中测试过 - 除了'namespace upvar'部分 - 所以我真的认为它应该适合你。) – 2012-03-26 10:13:49
哇,考虑我的想法。我必须阅读手册才能理解这一点。谢谢。也许很快我们会升级到更新的Tcl,但现在我坚持8.4。 – Matt 2012-03-27 15:18:24
啊,平常的事情,首先你写的Tcl自己OO系统; - )。 Tcl 8.4.18版本相当陈旧,新版本可能会使一些事情变得更加容易(尤其是8.6版本的Beta版本,它可能需要学习OO系统)。我很确定你想做什么是可能的,但它可能不会很快。最简单的方法可能是重写'名称空间导入',并让它创建别名而不是真正的导入。或者最好的可能是使用命名空间命令解析器,但那些在8.4中不可用。 – schlenk 2012-03-25 20:58:47
8.6中的OO系统也可作为8.5的扩展。 – 2012-03-26 09:33:59
请注意,对象系统很难正确对待。你可以做很多事情,但除非你准备做大量的工作,否则你会遇到困难。 – 2012-03-26 09:48:21