是否可以将参数的默认值设置为函数的 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\]}