gpt4 book ai didi

命名空间 : calling namespace procs give errors 内的 TclOO 类

转载 作者:行者123 更新时间:2023-12-04 21:53:37 31 4
gpt4 key购买 nike

我正在对 Tcl8.6 和 Rivet 中的 TclOO 进行一些试验,但我遇到了麻烦,因为我无法做我想做的事。

问题可以简单地通过 .rvt 中的以下代码重现。文件:

<?

proc dumbproc {} {
puts "this is dumbproc ([namespace current])"
}

oo::class create foo {
method bar {} {
puts "this is bar ([namespace current])"
dumbproc
}
}

set obj [foo new]

dumbproc

$obj bar

如果我只是看一下代码,它似乎应该按预期工作,但实际上并没有,因为 Rivet 包的微妙行为和选择的特定配置。

在这个例子中,我使用了 .rvt其代码在 ::request 中执行的文件命名空间,因此 dumbproc 的完全限定名称程序是 ::request::dumbproc .在 bar 内部调用名称解析算法时方法,它搜索 dumbproc里面::oo::Obj12 , 然后在 ::oo ,最后在 :: , 没有找到它并给出以下错误。

this is dumbproc (::request) this is bar (::oo::Obj16)

invalid command name "dumbproc"
while executing
"dumbproc"
(class "::request::foo" method "bar" line 3)
invoked from within
"$obj bar"
(in namespace eval "::request" script line 21)
invoked from within
"namespace eval request {
puts -nonewline ""


proc dumbproc {} {
puts "this is dumbproc ([namespace current])"
}

oo::class create..."

因此,Tcl 正确做它所做的事情,特性。但是这种行为是不可预测的,因为当您编写一些类代码时,您必须知道将在其中使用它的上下文。

确实,如果我删除开始的 <?,我会得到同样的错误铆钉魔术,把代码放在一个test.tcl里面文件并在交互式 session 中使用它:

$ tclsh
% namespace eval ::myns {source test.tcl}
this is dumbproc (::myns)
this is bar (::oo::Obj12)
invalid command name "dumbproc"

我试图通过将当前命名空间添加到类创建代码中来解决这个问题

::oo::class create [namespace current]::foo { ... }

然后,我还尝试创建 obj命名空间内的对象

::oo::class create [namespace current]::foo { ... }
namespace eval [namespace current] {set obj [[namespace current]::foo new]}

然后,我切换到 create类的方法,用于为对象提供一个包含命名空间的限定名称

foo create [namespace current]::obj
obj bar

但是一切都不成功。每次试验都表明,无论我怎么做,TclOO 类中的方法总是在其对象唯一命名空间中执行。我错了吗?

有没有办法得到我想要的? TclOO 不打算那样工作吗?在这种情况下,为什么?真正让我感到惊讶的是这种依赖于上下文的行为,我不确定这是不是正确的,但也许我完全错了,并且有合理的案例,我错过了。

最佳答案

每个 TclOO 对象的内部实际上是其自己的 命名空间。您可以在方法中使用 self namespacenamespace current 来获取命名空间的名称,或使用 info object namespace $theobj 来获取命名空间从任何地方。默认情况下放置在命名空间中的唯一命令是my(用于调用私有(private)方法),其他命名空间中的一些命令通过标准的Tcl namespace path机制(这是您如何获得可用的 selfnext

解决此问题的最简单方法可能是将其添加到 foo 类的构造函数中:

namespace path [list {*}[namespace path] ::request]

在您的特定情况下,您必须实际添加一个构造函数...

constructor {} {
namespace path [list {*}[namespace path] ::request]
# If you had a non-trivial constructor in a superclass, you'd need to call
# [next] too.
}

从长远来看,要求一种机制来添加到用于为类的对象设置默认 namespace 的列表中可能是合理的。如果您想要,请提交 feature request ……


[编辑]:如果您只是在将父命名空间添加到当前对象的命令解析路径之后,您可以通过添加更多魔法来实现:

oo::class create foo {
self {
method create args {
set ns [uplevel 1 {namespace current}]
next {*}[linsert $args 1 $ns]
}
method new args {
set ns [uplevel 1 {namespace current}]
next {*}[linsert $args 0 $ns]
}
}
constructor {creatorNS args} {
namespace path [list {*}[namespace path] $creatorNS]
}
method bar {} {
puts "this is bar ([namespace current])"
dumbproc
}
}

然后会自动将创建时的当前命名空间放在实例的路径上。如果你在很多类中这样做,你可能想创建一个包含大部分机器的元类,但是上面的技术(一些方法的 self declarationfoo 类对象本身上)适用于简单的情况。

关于命名空间 : calling namespace procs give errors 内的 TclOO 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13286190/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com