参数的默认值只能是在过程声明时计算出来的常量(通常是字面值,也就是说不需要使用
list
进行构建):
proc TestFunction [list [list paramVal [GetParameterValue]]] {
...
}
为了在过程调用时计算默认值,您需要将计算移入过程体中。有几种检测是否进行计算的方法,但它们归结为三个选项:使用标记值、获取调用中单词的数量,以及完全控制解析。
使用标记值
这个技巧是找到一些非常不可能被传递的值。例如,如果这是要显示给用户的文本片段,则仅包含ASCII NUL的值不会出现。将其放入默认值中,然后您可以确定是否已经使用默认值,并使用复杂代码提供的内容进行替换。
proc TestFunction {{paramVal "\u0000"}} {
if {$paramVal eq "\u0000"} {
set paramVal [GetParameterValue]
}
...
}
获取调用中单词的数量
这取决于info level
内省命令的能力。特别是,info level 0
报告了当前过程的实际参数的完整列表。稍微计算一下,我们就可以知道是否传递了真实值。
proc TestFunction {{paramVal "dummy"}} {
if {[llength [info level 0]] < 2} {
set paramVal [GetParameterValue]
}
...
}
这是一种完全通用的方法,因此不必担心有人提供意外情况,但如果有多个参数,则更加复杂,因为您需要自己计算应该有多少参数等。在这种情况下很简单,但随着参数数量的增加,这变得越来越困难。
完全控制解析过程
最终,您还可以决定创建一个过程,完全控制其参数的解析。为此,您可以给它一个单一的参数args
,然后您可以使用任何方法来处理实际的参数列表。(在这种情况下,我倾向于不将形式参数列表放在括号中仅限于这种情况,但那只是我的个人风格。)
proc TestFunction args {
if {[llength $args] == 0} {
set paramVal [GetParameterValue]
} elseif {[llength $args] == 1} {
set paramVal [lindex $args 0]
} else {
return -code error -errorcode {TCL WRONGARGS} \
"wrong # args: should be \"TestFunction ?paramVal?\""
}
...
}
目前,这是实现任何高级功能的唯一方法,例如在强制参数之前设置可选参数。如果您在C中实现该命令,那么这基本上就是您必须要做的,尽管需要进行不同语言的调整。缺点是,与使用内置的基本参数解析支持代码相比,它确实更费力。