是否可以将参数的默认值设置为函数的返回值? (TCL)

时间:2019-02-04 22:02:41

标签: tcl

在TCL中,参数的默认值是否可以作为函数调用的返回值?

proc GetParameterValue { } {
    # calculation for value...
    return value
}

proc TestFunction { {paramVal [GetParameterValue]} } { 
    puts $paramVal
}

TestFunction

这将导致打印“ [GetParameterValue]”。而不是调用过程GetParameterValue。是否可以在TCL中做到这一点,还是需要重新设计这段代码?

2 个答案:

答案 0 :(得分:4)

参数的默认值只能是您在声明过程时计算的常量(最常见的是它们是文字,这意味着您无需使用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命令的实现所提供的内置基本参数解析支持代码相比,这肯定是更多的工作。

答案 1 :(得分:1)

这是对Donal详尽回答的补充。过去,有时我会借助[subst]来帮助计算默认值:

proc GetParameterValue {} { return computedDefault }

proc TestFunction {{paramVal [GetParameterValue]}} { 
    puts [subst -novariables $paramVal]
}

TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}

这避免了对参数的完全控制(实现),并搭载在内置参数处理程序上。它还允许使用匿名proc而不是显式命名的proc来计算默认值:

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\]}