在TCL中,我们可以这样传递参数吗?

在TCL中,我们可以这样传递参数吗?,tcl,parameter-passing,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的值是“罗纳尔多”,它已经是双引号了,我们是否

我对在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的值是“罗纳尔多”,它已经是双引号了,我们是否需要在参数列表中像这样添加双引号:player_name“$name”?在我们执行“全局名称”命令之前,player_name的默认值是“罗纳尔多”吗?既然如此,为什么我们需要在程序中使用“全局名称”命令呢?

,因为它不能正常工作;
$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\u PLAYER\u INFO
本身,在对上述定义的有效调用中,它将是长度为2或3的列表。一旦列表可用,在
llength
和数值比较中,检查其长度是一个简单的练习。(不过,使用sentinel值更容易,并且在99.99%的情况下有效。)

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

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
    }
    ...
}
proc GET\u PLAYER\u INFO参数{
如果{[llength$args]<1 |[llength$args]>2}{
返回-代码错误“错误”参数:应为“获取球员信息球员id球员姓名”
}
设置玩家id[lindex$args 0]
如果{[llength$args]>1}{
设置玩家名称[lindex$args 1]
}否则{
设置播放器名称$::名称
}
...
}
正如你所看到的,这是相当冗长的