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

时间:2012-03-16 11:36:14

标签: tcl parameter-passing

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

set name "Ronaldo"

proc GET_PLAYER_INFO {player_id {player_name "$name"}} {
    global name
    puts $player_name
}

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

1 个答案:

答案 0 :(得分:7)

这不会起作用;根本不会对$name进行评估,因此默认值为五个字符。

如果您在创建过程时绑定了默认值,则可以这样做:

proc GET_PLAYER_INFO [list player_id [list player_name $name]] {
    ...
}

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

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

proc GET_PLAYER_INFO {player_id {player_name ""}} {
    if {$player_name eq ""} {
        set player_name $::name
    }
    ...
}

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

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

proc GET_PLAYER_INFO {player_id {player_name ""}} {
    if {[llength [info level 0]] == 2} {
        set player_name $::name
    }
    ...
}

命令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
    }
    ...
}

正如你所看到的,这是相当冗长的......