【问题标题】:Tcl: How do I call a proc from a different namespace, while also passing my proc a variable from its namespace?Tcl:如何从不同的命名空间调用 proc,同时从其命名空间传递我的 proc 变量?
【发布时间】:2019-07-23 23:34:51
【问题描述】:

我定义了两个脚本:第一个脚本在第二个脚本中调用一个 proc。第二个脚本定义了一个命名空间fooSpace,在fooSpace 中定义了一个变量fooValue,并在fooSpace 中定义了一个proc myProc

在我的第一个脚本中,我想用 myValue 的参数调用我的 proc。我希望我的 proc 测试myValue 是否存在于fooSpace 中作为fooValue。如果是这样,该函数将使用fooValue 来做一些事情。

如果我理解正确,upvar 引用了调用者的命名空间,在我的例子中,它与函数的命名空间不同。但我也不认为我可以在我的 proc 中执行 variable $myvalue ,对吗?如何让我的 proc 使用fooSpace 中定义的变量?

我下面的代码返回“无法读取 $fooSpace”

这是我的第一个脚本(位于 alpha.tcl)的样子:

source bravo.tcl
namespace import fooSpace::myProc

# call the fuction
myProc apples

这是我的第二个脚本(位于 bravo.tcl)的样子:

namespace eval fooSpace {
    namespace export myProc
    set apples "Apples are 3 for a dollar"

    proc myProc {myValue} {
        upvar $fooSpace::$myValue fruit
        if {[info exists fruit] == 1} {
            puts "$fruit"
        } else {
            puts "we don't have any $fruit today"
        } 
    }
}

【问题讨论】:

  • 请。尝试改进你的问题措辞和例子。 (a) 示例不是最少的(例如,不需要source 来证明感知到的问题); (b) 它们不起作用(myfunctionmyProc),(c) 您没有报告向您报告的错误消息的正确措辞:Can't read $fooSpace 不是 Tcl 错误消息。

标签: scope namespaces tcl


【解决方案1】:

您可以使用namespace upvar 做您想做的事,它是为查看另一个命名空间中的变量而设计的:

namespace upvar $fooSpace $myValue fruit

或者,您可以使用 upvar 来执行此操作,但随后您需要停止替换 fooSpace 变量名,以免之后包含命名空间分隔符(或者您最终谈论的是其中包含空名称的变量那个命名空间,它可能不存在)。这种引用控制是使用${…} 完成的,如下所示:

upvar ${fooSpace}::$myValue fruit

(你也可以使用${fooSpace}::${myValue},解析后都一样。)

我建议您使用namespace upvar:它的效率要高得多,因为它根本不需要重新解析变量名。

【讨论】:

  • namespace upvar 命令的创建是为了加速 Snit 包(在 Tcllib 中),该包在其实现中大量使用取自另一个命名空间的变量。它比普通的upvar 和字符串操作要快得多,尤其是当您从同一个命名空间导入多个变量时。
  • 嗨,多纳尔。 namespace_upvar 正是我正在寻找的 Tcl 8.7 应用程序。然而,我刚刚发现我将运行我的代码的工作台实际上使用的是 Tcl 8.4。任何想法我将如何获得上面相同的代码来使用该版本? (我不确定我是否应该修改我原来的问题,因为答案肯定是相关的,问一个新问题,或者在 cmets 中提问)。接受方向/建议。
【解决方案2】:

如何让我的 proc 使用 fooSpace 中定义的变量?

您对upvar 的使用是虚假的,您错过了级别参数#0

upvar "#0" [namespace current]::$myValue fruit

此外,$fooSpace 没有引用命名空间 fooSpace,而是引用该名称的 proc-local 变量(因此出现 can't read "fooSpace": no such variable 错误);因此:

[namespace current]::$myValue

变成了

::fooSpace::$myValue

但我也不认为我可以在我的 proc 中执行变量 $myvalue

这取决于,如果你想使用链接变量fruit,不,variable 命令不会给你那个。但是你当然可以像这样引用命名空间变量:

 variable $myValue

小建议:myValue 最好是myVarmyVarName,因为参数表示(命名空间)变量名称(不是这些变量存储的值)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多