我有一个关于在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中使用“全局名称”命令?
答案 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
}
...
}
正如你所看到的,这是相当冗长的......