Tcl 例外情况;用括号括起您的expr表达式“;规则。什么';发生什么事了?

Tcl 例外情况;用括号括起您的expr表达式“;规则。什么';发生什么事了?,tcl,Tcl,我在一个变量中有一个数字,比如说10,在另一个变量中有一个字符串,比如+1或-2。在上述情况下,我需要评估10+1或10-2 所以,我有 set foo 10 set garp -1 如果我这样做 expr $foo $garp 一切都很好(我得了9分) 啊!!但一般来说,应该在expr表达式周围加上大括号 expr {$foo $garp} 在表达式$foo@.$garp中的@@处缺少运算符,因此失败 同样地 expr [concat $foo $garp] 工作很好,但是 expr

我在一个变量中有一个数字,比如说10,在另一个变量中有一个字符串,比如+1或-2。在上述情况下,我需要评估10+1或10-2

所以,我有

set foo 10
set garp -1
如果我这样做

expr $foo $garp
一切都很好(我得了9分)

啊!!但一般来说,应该在
expr
表达式周围加上大括号

expr {$foo $garp}
在表达式$foo@.$garp中的@@处缺少运算符,因此失败

同样地

expr [concat $foo $garp]
工作很好,但是

expr {[concat $foo $garp]}
返回
10-1

我不想在没有真正理解发生了什么事情的情况下保持表达式的完整性,因为我担心,否则我或其他人会在表达式周围加上大括号,代码将停止工作

“正确”的方法是什么?

在这种情况下

expr {$foo + $garp}
“始终用括号括住表达式”规则源于这样一个事实,即最好绕过参数求值步骤,将表达式字符串的求值完全留给
expr
(因为它更安全1,并产生更有效的字节码2)

要使其正常工作,根据
expr
文档中列出的规则,传递给
expr
的字符串必须是合法的(无支撑的表达式不必是合法的,只要参数求值步骤使其合法)。由此可知,任何时候您需要参数求值来帮助您创建合法表达式字符串都是“always Brake”规则的一个例外(这可能暗示您需要重新考虑代码3的结构)

字符串
{$foo$garp}
是非法的,因为变量替换只能是表达式中的操作数,这意味着我们有两个没有运算符的操作数。字符串
“$foo$garp”
通过参数计算转换为合法表达式,因为减号运算符被重新解释为减法运算符

如果您有一组成对获得的值,
a
b
,并且您希望添加这些值,
expr$a$b
如果您确定它们始终有符号,则可能会起作用。不过这很脆弱。最好用其中一种

expr {$a + $b}
tcl::mathop::+ $a $b
expr [join [list $a $b] +]
(第一个是我们上面讨论过的解决方案。第二个是通过在
expr
之外使用
+
运算符避免双重替换:变量由参数计算器计算,而不是由命令计算。第三个变量具有双重替换的所有问题,主要是为了完整性。它是尽管如此,还是比只表达$a$b更好。)

文件: , , , ,

1) 例如,给定敌对参数时,参数计算器可以将表达式中的
$foo
替换为
[exec rm-rf*]
或您所称的任何内容,然后将在
expr
内执行命令替换。如果通过支撑表达式不允许双重替换,则不太可能发生这种情况

expr {$foo $garp}
2) 字节编译器可以分析大括号表达式,并用更高效的内联计算替换对
expr
的调用。对于无支撑的字符串,编译器除了设置对
expr
的调用外,没有其他选择,不管表达式是什么

3) 看似矛盾的是,通过某个受信任的方法构造表达式并通过变量(
set myexpr[…];expr$myexpr
)无支撑地传递它并不成问题,因为这样您仍然可以完全控制表达式的内容,当然,你也不需要依靠参数计算器来修补它。不过,您不会得到字节码优化。

在这种情况下

expr {$foo + $garp}
“始终用括号括住表达式”规则源于这样一个事实,即最好绕过参数求值步骤,将表达式字符串的求值完全留给
expr
(因为它更安全1,并产生更有效的字节码2)

要使其正常工作,根据
expr
文档中列出的规则,传递给
expr
的字符串必须是合法的(无支撑的表达式不必是合法的,只要参数求值步骤使其合法)。由此可知,任何时候您需要参数求值来帮助您创建合法表达式字符串都是“always Brake”规则的一个例外(这可能暗示您需要重新考虑代码3的结构)

字符串
{$foo$garp}
是非法的,因为变量替换只能是表达式中的操作数,这意味着我们有两个没有运算符的操作数。字符串
“$foo$garp”
通过参数计算转换为合法表达式,因为减号运算符被重新解释为减法运算符

如果您有一组成对获得的值,
a
b
,并且您希望添加这些值,
expr$a$b
如果您确定它们始终有符号,则可能会起作用。不过这很脆弱。最好用其中一种

expr {$a + $b}
tcl::mathop::+ $a $b
expr [join [list $a $b] +]
(第一个是我们上面讨论过的解决方案。第二个是通过在
expr
之外使用
+
运算符避免双重替换:变量由参数计算器计算,而不是由命令计算。第三个变量具有双重替换的所有问题,主要是为了完整性。它是尽管如此,还是比只表达$a$b更好。)

文件: , , , ,

1) 例如,给定敌对参数时,参数计算器可以将表达式中的
$foo
替换为
[exec rm-rf*]
或您所称的任何内容,然后将在
expr
内执行命令替换。如果通过支撑表达式不允许双重替换,则不太可能发生这种情况

expr {$foo $garp}
2) 字节编译器可以分析大括号表达式,并将对
expr
的调用替换为
expr {$foo + $garp}