How do you store the namespace variable and its nested namespace children (its variable, etc) states in a file in TCL?

huangapple go评论65阅读模式
英文:

How do you store the namespace variable and its nested namespace children (its variable, etc) states in a file in TCL?

问题

如何在TCL中将命名空间变量及其嵌套命名空间子项(变量等)的状态保存到文件中?

英文:

How do you save the namespace variable and its nested namespace children (its variable, etc) states in a file in TCL?

答案1

得分: 1

# 将变量内容存储在命名空间树中相当容易,将过程存储在命名空间中也是如此。存储可能存在的其他命令和变量追踪... 要困难得多!此外,这些变量中的值可能会命名临时的事物,比如套接字通道。

# 这里做的是简单的事情,将生成的 Tcl 脚本写入一个打开的通道;写入文件只是对此的一个简单包装。
proc storeNamespace {channel namespaceName} {
    # 设置命名空间及其变量
    set initBody {}
    foreach var [info vars $namespaceName::*] {
        # 棘手的一点是,在写入那里的变量之前需要在命名空间中调用 [variable]
        append initBody "\n" [list variable [namespace tail $var]]
    }
    puts $channel [list namespace eval $namespaceName $initBody]

    # 现在我们实际上可以将变量的内容写出来
    foreach var [info vars $namespaceName::*] {
        upvar 1 $var v
        # 两种情况,数组和简单变量
        if {[array exists v]} {
            puts $channel [list array set $var [array get v]]
        } else {
            puts $channel [list set $var $v]
        }
    }

    # 也保存过程
    foreach p [info procs $namespaceName::*] {
        # 需要额外的工作来处理带有默认值的参数
        set args [lmap a [info args $p] {
            if {[info default $p $a def]} {
                list $a $def
            } else {
                list $a
            }
        }]
        # 写入过程定义
        puts $channel [list proc $p $args [info body $p]]
    }

    # 并递归处理子命名空间
    foreach ns [namespace children $namespaceName] {
        storeNamespace $channel $ns
    }
}

# 示例:
storeNamespace stdout ::foo
英文:

Storing the contents of the variables in a tree of namespaces is easy enough, as is storing the procedures in the namespaces. Storing the other commands that might be there and the variable traces... much harder! Plus the values in those variables might name ephemeral things like socket channels.

This does the simple thing, writing a generated Tcl script to an open channel; writing to a file is just a trivial wrapper around this.

proc storeNamespace {channel namespaceName} {
    # Set up the namespace and its variables
    set initBody {}
    foreach var [info vars $namespaceName::*] {
        # Tricky point; need to call [variable] in the NS before writing to vars there
        append initBody "\n" [list variable [namespace tail $var]]
    }
    puts $channel [list namespace eval $namespaceName $initBody]

    # Now we can actually write the contents of the variables out
    foreach var [info vars $namespaceName::*] {
        upvar 1 $var v
        # Two cases, arrays and simple variables
        if {[array exists v]} {
            puts $channel [list array set $var [array get v]]
        } else {
            puts $channel [list set $var $v]
        }
    }

    # Save the procedures too
    foreach p [info procs $namespaceName::*] {
        # Need to do extra work to handle arguments with defaults
        set args [lmap a [info args $p] {
            if {[info default $p $a def]} {
                list $a $def
            } else {
                list $a
            }
        }]
        # Write the procedure definition
        puts $channel [list proc $p $args [info body $p]]
    }

    # And recurse for the child namespaces
    foreach ns [namespace children $namespaceName] {
        storeNamespace $channel $ns
    }
}

# Example:
storeNamespace stdout ::foo

huangapple
  • 本文由 发表于 2023年6月22日 02:07:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526045.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定