在TCL中,我们可以通过这种方式传递参数吗?

5 tcl parameter-passing

我有一个关于在Tcl中传递参数的问题,涉及以下代码:

set name "Ronaldo"

proc GET_PLAYER_INFO {player_id {player_name "$name"}} {
    global name
    puts $player_name
}
Run Code Online (Sandbox Code Playgroud)

关于上面的代码,我们有一个全局变量"name",并且在proc GET_PLAYER_INFO的参数列表中,参数player_name的默认值设置为"$ name"?如果name的值是"ronaldo",它已经是双引号,我们是否需要在参数列表中加上双引号,如下所示:player_name"$ name"?在我们执行"全局名称"命令之前,player_name的默认值是"Ronaldo"吗?是这样,为什么我们需要在proc中使用"全局名称"命令?

Don*_*ows 7

这不会起作用; 该$name不会都那么默认的将是那些文字五个字符进行评估.

如果您在创建过程时绑定了默认值,则执行以下操作:

proc GET_PLAYER_INFO [list player_id [list player_name $name]] {
    ...
}
Run Code Online (Sandbox Code Playgroud)

也就是说,参数proc只是你可以用Tcl命令和替换构造的正常事物.这是关于Tcl的一件大事.

但是,如果您想$name在调用过程时对其进行评估,则必须采用不同的方法.如果你有一些永远不会用于玩家名称的值(例如,空字符串)那么它很容易:

proc GET_PLAYER_INFO {player_id {player_name ""}} {
    if {$player_name eq ""} {
        set player_name $::name
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在那里使用了完全限定的变量名称.还有其他方法可以获得该名称(例如,with global,with upvar,with variable,...)

事情变得棘手的地方是你根本没有合适的哨兵价值.那时,你必须看到实际提供了多少个参数:

proc GET_PLAYER_INFO {player_id {player_name ""}} {
    if {[llength [info level 0]] == 2} {
        set player_name $::name
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

该命令info level 0将参数字的完整列表返回到当前过程调用.这包括GET_PLAYER_INFO自身,并且在对上述定义的有效调用中将是长度为2或3的列表.一旦列表可用,检查其长度是一个简单的练习llength和数字比较.(使用标记值更容易,并且在99.99%的情况下有效.)

最后一个选项是使用特殊的args形式参数并手动进行解析:

proc GET_PLAYER_INFO args {
    if {[llength $args] < 1 || [llength $args] > 2} {
        return -code error "wrong # args: should be \"GET_PLAYER_INFO player_id ?player_name?\""
    }
    set player_id [lindex $args 0]
    if {[llength $args] > 1} {
        set player_name [lindex $args 1]
    } else {
        set player_name $::name
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

如你所见,这是啰嗦......