【问题标题】:How to call a proc from a particular sourced file if there are multiple sourced files with same proc names?如果有多个具有相同 proc 名称的源文件,如何从特定源文件调用 proc?
【发布时间】:2019-08-13 06:51:25
【问题描述】:

我正在尝试编写一个包装 tcl,它获取多个 tcl 文件,并且这些 tcl 文件有一些在多个文件中具有相同名称的 proc。如何从特定文件显式调用 proc?

我搜索了堆栈溢出并遇到了 proc rename,但我想知道是否还有其他解决方案。也许更干净。

【问题讨论】:

  • 抱歉没有举个例子。我无法发布示例代码。它一直说我有一些格式错误。
  • 尝试发布代码,有人会帮你格式化。
  • 据我所知,正确的做法是使用namespaces。假设第一个文件使用命名空间a,第二个文件使用命名空间b,那么您可以使用::a::procname 从第一个文件调用procs,使用::b::procname 从第二个文件调用。
  • 使用命名空间或解释器来分隔事物是正确的方法。使用哪一个取决于您想要什么:命名空间(非常!)重量更轻,解释器提供强大的分离(几乎与使用子进程一样强大)。

标签: tcl


【解决方案1】:

这有点棘手,但您可以继续使用从解释器来区分文件。

add.tcl

proc calculate {a b} {
        return [expr {$a+$b}]
}

sub.tcl

proc calculate {a b} {
        return [expr {$a-$b}]
}

file_src_manager.tcl

array set tclEngine {}
set files  {add.tcl sub.tcl}
foreach f $files {
  # Creating slave interpreter for each files.
  set tclEngine($f) [interp create]
  # Sourcing them in separate interpreter
  if {[catch {interp eval $tclEngine($f) "source $f"} issue]} {
    puts "Failed to source $f. Reason - $issue"
  }
}
# Calling add.tcl file's calculate method
puts [interp eval $tclEngine(add.tcl) "calculate 5 3"]
# Calling sub.tcl file's calculate method
puts [interp eval $tclEngine(sub.tcl) "calculate 5 3"]

输出

8
2

参考:interp

【讨论】:

    【解决方案2】:

    您可以在单独的命名空间中组织source'ed proc,例如,通过将脚本名称重新用作命名空间名称:

    add.tcl

    namespace eval ::[file tail [info script]] {
        proc calculate {a b} {
            return [expr {$a+$b}]
        }
        namespace export calculate
    }
    

    sub.tcl

    namespace eval ::[file tail [info script]] {
        proc calculate {a b} {
            return [expr {$a-$b}]
        }
        namespace export calculate
    }
    

    然后,在您的主脚本中,您可以在不同的 proc 池之间来回切换,例如使用[namespace import]:

    % source add.tcl
    % source sub.tcl
    % namespace import -force ::add.tcl::*
    % calculate 5 3
    8
    % namespace import -force ::sub.tcl::*
    % calculate 5 3
    2
    

    备注

    • [info script] 返回当前来源的脚本文件(由source 命令在后台设置)。
    • 确保[namespace export] 池化过程。否则,它们不会被导入。
    • namespace import 上使用-force 标志将静默替换目标命名空间中的同名命令(procs)。
    • 在从解释器上使用命名空间(如 Dinesh 所建议的那样)是一个后果问题和您的用例:过程是否需要共享某些状态(变量)或某些资源(通道)?是否应该限制 proc 仅使用其 source 上下文中的文件?等
    • 您当然可以定义自己的 source 变体,以避免在每个 source'ed 脚本中出现样板。

    【讨论】:

    • 正如@Jerry 所指出的,您当然总是可以使用命名空间限定符明确指向池化过程:::add.tcl::calculate, ::sub.tcl::calculate, ...
    • 在我的例子中,proc 是互斥的,但它们确实共享包装脚本中的变量。在这种情况下,口译员会更好地工作吗?
    • 如果他们本着globalupvar的精神共享变量,那么命名空间的方式就更合适了。
    猜你喜欢
    • 2019-05-29
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 2021-10-14
    • 2022-06-14
    • 1970-01-01
    • 2021-11-30
    • 2012-12-31
    相关资源
    最近更新 更多