是否可以将参数的默认值设置为函数的 return ? (TCL)
Is is possible to set the default values of parameters to be the return of a function? (TCL)
在 TCL 中,参数的默认值可以是函数调用的 return 值吗?
proc GetParameterValue { } {
# calculation for value...
return value
}
proc TestFunction { {paramVal [GetParameterValue]} } {
puts $paramVal
}
TestFunction
这导致打印“[GetParameterValue]”。而不是调用过程 GetParameterValue。这可以在 TCL 中完成还是我需要重新设计这段代码?
参数的默认值只能是您在声明过程时计算的常量(最常见的是,它们是文字,这意味着您不需要使用 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} {
# Note that the command name itself is always present
set paramVal [GetParameterValue]
}
...
}
这是一种完全通用的方法,所以不用担心有人提供了意外的边缘情况,但是当你有多个参数时会更复杂,因为你需要计算出应该出现多少个参数等等你自己。在这种情况下这很简单,但是随着您有更多参数,这会变得越来越困难。
完全控制解析
最终,您还可以决定制作一个完全控制其参数解析的过程。你可以通过给它一个参数 args
来做到这一点,然后你可以使用你想要的任何方法来处理实际的参数列表。 (我倾向于不将正式参数列表放在括号中 在这种情况下 但这只是我自己的风格。)
proc TestFunction args {
if {[llength $args] == 0} {
set paramVal [GetParameterValue]
} elseif {[llength $args] == 1} {
set paramVal [lindex $args 0]
} else {
# IMPORTANT! Let users discover how to use the command!
return -code error -errorcode {TCL WRONGARGS} \
"wrong # args: should be \"TestFunction ?paramVal?\""
}
...
}
这是目前做任何真正高级的事情的唯一方法,例如,在强制参数之前有可选参数。如果您在 C 中实现命令,这也几乎是您在 C 中必须做的事情,尽管针对不同的语言进行了调整。缺点是它肯定比使用 proc
命令的实现提供的内置基本参数解析支持代码要多工作。
这是对 Donal 详尽回答的补充。过去,我有时求助于 [subst]
来计算默认值:
proc GetParameterValue {} { return computedDefault }
proc TestFunction {{paramVal [GetParameterValue]}} {
puts [subst -novariables $paramVal]
}
TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}
这避免了(实现)对参数的完全控制的需要,并且搭载在内置参数处理程序上。它还允许使用匿名过程而不是显式命名的过程来计算默认值:
proc TestFunction {{paramVal "[apply {{} { return computedValue }}]"}} {
puts [subst -novariables ${paramVal}]
}
TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}
不言而喻,背后也有一些假设,根据自己的应用情况变成重要的限制条件:
在参数列表中使用方括号作为默认值,并在参数变量的使用位置放置 [subst]
时必须遵守一些规则。
它假定您对参数有一定的控制权,或者您可以保证某些特殊用途的字符不是参数值域的有效成员。
观看:
TestFunction {[xxx]}
投掷
invalid command name "xxx"
并且必须经过消毒才能达到
TestFunction {\[xxx\]}
在 TCL 中,参数的默认值可以是函数调用的 return 值吗?
proc GetParameterValue { } {
# calculation for value...
return value
}
proc TestFunction { {paramVal [GetParameterValue]} } {
puts $paramVal
}
TestFunction
这导致打印“[GetParameterValue]”。而不是调用过程 GetParameterValue。这可以在 TCL 中完成还是我需要重新设计这段代码?
参数的默认值只能是您在声明过程时计算的常量(最常见的是,它们是文字,这意味着您不需要使用 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} {
# Note that the command name itself is always present
set paramVal [GetParameterValue]
}
...
}
这是一种完全通用的方法,所以不用担心有人提供了意外的边缘情况,但是当你有多个参数时会更复杂,因为你需要计算出应该出现多少个参数等等你自己。在这种情况下这很简单,但是随着您有更多参数,这会变得越来越困难。
完全控制解析
最终,您还可以决定制作一个完全控制其参数解析的过程。你可以通过给它一个参数 args
来做到这一点,然后你可以使用你想要的任何方法来处理实际的参数列表。 (我倾向于不将正式参数列表放在括号中 在这种情况下 但这只是我自己的风格。)
proc TestFunction args {
if {[llength $args] == 0} {
set paramVal [GetParameterValue]
} elseif {[llength $args] == 1} {
set paramVal [lindex $args 0]
} else {
# IMPORTANT! Let users discover how to use the command!
return -code error -errorcode {TCL WRONGARGS} \
"wrong # args: should be \"TestFunction ?paramVal?\""
}
...
}
这是目前做任何真正高级的事情的唯一方法,例如,在强制参数之前有可选参数。如果您在 C 中实现命令,这也几乎是您在 C 中必须做的事情,尽管针对不同的语言进行了调整。缺点是它肯定比使用 proc
命令的实现提供的内置基本参数解析支持代码要多工作。
这是对 Donal 详尽回答的补充。过去,我有时求助于 [subst]
来计算默认值:
proc GetParameterValue {} { return computedDefault }
proc TestFunction {{paramVal [GetParameterValue]}} {
puts [subst -novariables $paramVal]
}
TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}
这避免了(实现)对参数的完全控制的需要,并且搭载在内置参数处理程序上。它还允许使用匿名过程而不是显式命名的过程来计算默认值:
proc TestFunction {{paramVal "[apply {{} { return computedValue }}]"}} {
puts [subst -novariables ${paramVal}]
}
TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}
不言而喻,背后也有一些假设,根据自己的应用情况变成重要的限制条件:
在参数列表中使用方括号作为默认值,并在参数变量的使用位置放置
[subst]
时必须遵守一些规则。它假定您对参数有一定的控制权,或者您可以保证某些特殊用途的字符不是参数值域的有效成员。
观看:
TestFunction {[xxx]}
投掷
invalid command name "xxx"
并且必须经过消毒才能达到
TestFunction {\[xxx\]}