这听起来可能很傻。请耐心等待。在玩expr
时,我遇到了以下场景
proc badExpr { a b } {
return expr $a+$b
}
proc goodExpr { a b } {
return [ expr {$a+$b} ]
}
puts "Bad Expression Result : --->[ badExpr 1 3 ]<-----"
puts "Good Expression Result : [ goodExpr 1 3 ]"
输出:
Bad Expression Result : ---><-----
Good Expression Result : 4
正如您所看到的,proc badExpr
正在返回一个空字符串。只是出于好奇,我很想知道为什么它会返回一个空字符串?
(1)proc-badExpr{a b}{return expr$a+$b}
在上面的badExpr中,您没有使用TCL expr命令。上面的expr和其他字符串一样被处理。如果确实要使用命令expr
,则必须将其放在方括号中。所以应该是return [expr $a + $b]
return命令返回一个字符串值,您还可以指定各种选项。根据以下文件http://www.tcl.tk/man/tcl/TclCmd/return.htm最后一个值是实际的返回结果。
return ?result?
return ?-code code? ?result?
return ?option value ...? ?result?
然而,如果您有偶数个任意args,它不会返回任何内容。我不确定引擎盖下发生了什么,但当你使用-code或option时,你会有一个与之相关的value参数。因此,它可能会将每一对都视为option/value或code/value,并返回最后一个未关联的项目。
#Returns 3
return 1 2 3 4 3
#Returns nothing
return 1 2 3
(2)expr{$a+$b}之所以有效,是因为它是进程中的最后一个表达式。I如果一个过程没有执行显式返回,那么它的返回值是在过程主体中执行的最后一个命令的值它不需要是expr{$a+$b},它可以是你的badExpr中的expr$a+$b。
badExpr
应该是这样的:
proc badExpr { a b } {
return [expr $a+$b]
}
实际上得到的是weirdExpr
:
proc badExpr { a b } {
return expr $a+$b
}
这到底有什么作用?它在结果字典中设置内容。Tcl结果实际上应该被视为三重:结果代码(一个小整数,在本例中为0
表示OK——1
表示抛出的错误,通常很少有其他可以忽略的错误)、结果值(通常返回的值)和结果字典。结果字典主要用于错误,用于保存堆栈跟踪(用于填充errorInfo
全局变量)、发生错误的行号、错误的计算机可读描述(用于填充errorCode
全局变量)等,但它可以保存任何旧的东西。你在其中加入了一些非常奇怪的东西(因为return
就是这样工作的);系统定义的键都以CCD_ 12开头,使它们看起来像普通选项(字典本身通常被称为选项字典)。
让我们使用catch
的双变量形式来展示这一点(第二个变量捕获字典):
% proc weirdExpr { a b } {
return expr $a+$b
}
% catch {weirdExpr 1 3} p q
0
% puts $p
% puts $q
expr 1+3 -code 0 -level 0
是的,里面有一个有趣的条目,叫做expr
,它的值是1+3
…
简而言之,问题是expr
的调用周围没有括号。
return expr $a+$b ;# no worky
return [expr $a+$b] ;# works (but you should have braces around the arguments)
它没有被清楚地记录下来,但return
似乎接受任意数量的参数。如果参数列表大小相等,则该命令将返回空字符串。如果参数的数量为奇数,则返回最后一个参数。这与文档一致:正常参数列表由一个可选结果值组成,该值前面有零个或多个选项名称/值对。这仍然有点出乎意料,因为人们会认为选项名称被限制为有用的名称。
哦!如果return
是脚本中的最后一个命令,而它的唯一参数是脚本求值(括号内的代码),则可以始终跳过return
(字节编译器无论如何都会将其删除)。
proc goodExpr { a b } {
return [ expr {$a+$b} ]
}
与相同
proc goodExpr { a b } {
expr {$a+$b}
}
文档:expr,返回