Tcl中返回空字符串的格式错误的expr

Tcl中返回空字符串的格式错误的expr,tcl,expr,Tcl,Expr,这听起来可能很傻。请容忍我。在玩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 ]" p

这听起来可能很傻。请容忍我。在玩
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 ]"
proc badExpr{a b}{
返回表达式$a+b
}
proc goodExpr{a b}{
返回[expr{$a+$b}]
}

放置“错误表达式结果:-->[badExpr 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 } { 
    expr {$a+$b}
}
文档:,

(1) 程序badExpr{a b}{ 返回表达式$a+b }

在上面的badExpr中,您没有使用TCL expr命令。上面的expr与任何其他字符串一样处理。如果要使用命令
expr
,则必须将其放在方括号中。因此,它应该是
return[expr$a+$b]

return命令返回一个字符串值,您还可以指定各种选项。根据下面的文档,最后一个值是实际返回结果

return ?result?
return ?-code code? ?result?
return ?option value ...? ?result?
但是,如果您有偶数个任意参数,它不会返回任何内容。我不确定引擎盖下发生了什么,但当您使用-code或option时,您将有一个与之关联的值参数。因此,它似乎可能会将每一对视为option/value或code/value,并返回最后一个未关联的项作为结果。

#Returns 3
return 1 2 3 4 3

#Returns nothing
return 1 2 3
(2)
expr{$a+$b}之所以有效,是因为它是过程中的最后一个表达式。如果一个过程没有执行显式返回,那么它的返回值就是在过程体中执行的最后一个命令的值。它不需要是expr{$a+$b},它可以像在您的badExpr中那样表示$a+$b。

有趣的是,
badExpr
将如下所示:

proc badExpr { a b } { 
    return [expr $a+$b]
}
你实际上得到的是
weirdExpr

proc badExpr { a b } { 
    return expr $a+$b
}
这到底是做什么的?它在结果字典中设置了一些东西。Tcl结果实际上应该被认为是三件事的三重:结果代码(一个小整数,在本例中,对于OK来说
0
1
将是一个抛出的错误,很少有其他的结果可以忽略)一个结果值(通常返回的内容)和结果字典。结果字典主要用于错误,用于保存堆栈跟踪(用于填充
errorInfo
全局变量)、发生错误的行号、计算机可读的错误描述(用于填充
errorCode
全局变量)等,但它可以保存任何旧的东西。而且你在其中加入了一些非常奇怪的东西(因为
return
就是这样工作的);系统定义的键都以
-
开头,使它们看起来像普通选项(字典本身通常被称为选项字典)

让我们使用两个变量形式的
catch
(第二个变量捕获字典)来展示这一点:


是的,里面有一个有趣的条目叫做
expr
,它的值是
1+3

谢谢多纳尔。现在有意义了。
proc badExpr { a b } { 
    return [expr $a+$b]
}
proc badExpr { a b } { 
    return expr $a+$b
}
% 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