语法TCL:_ @ _处缺少运算符

时间:2015-10-29 23:37:56

标签: syntax tcl tk

我试图获得列表的最大值,列表可能包含零,0。在Tcl 8.5中,当我运行时:

set x {-5 -4 -3 -2 -1 0 1 2 3 4 5}
set maxx [expr max($x)]
set minx [expr min($x)]
puts "$minx $maxx"

我收到错误:

missing operator at _@_
in expression "max(-5 -4 -3 -2 -1 _@_0 1 2 3 4 5)"
(parsing expression "max(-5 -4 -3 -2 -1 0 1...")
invoked from within
"expr "max($x)""
invoked from within
"set maxx [expr "max($x"]"

我尝试过语法变异和我能找到的资源。

作为一种解决方法,我将使用lsort并获取该列表的第一个/最后一个元素,但我真的想知道我在这里做错了什么:/谢谢。

2 个答案:

答案 0 :(得分:4)

Tcl表达式有点不同,你不能直接将列表填入其中并期望它能够正常工作。

我建议您直接使用::tcl::mathfunc::max,使用参数展开({*}):

set maxx [::tcl::mathfunc::max {*}$x]
set minx [::tcl::mathfunc::min {*}$x]

但如果您仍想使用expr,可以尝试使用join创建有效的表达式:

set maxx [expr "max([join $x ,])"]
set minx [expr "min([join $x ,])"]

但是这个性能很差并且可以被利用(代码注入),考虑x的这个输入:{-1 {[puts "Not good"; exit]} 2}

答案 1 :(得分:2)

一点阐述。如果它不合适,请告诉我。

对于解释器,调用foo {{a a a} {b b} c}只有一个参数(由三个项或单词组成),foo {a a a} {b b} c有三个参数(每个参数由三个,两个或一个项或单词组成)。只要命令的调用是正确的列表,解释器就不关心参数组成的内容或者它们的数量。命令otoh通常关心参数的数量和内容。

这意味着我们可能不得不偷偷摸摸。我们可以将foobar分配给变量x吗?是的,但不是set x foo bar,因为set命令(不是解释器)需要一个或两个参数(变量名称和零或一个值)。如果我们将其作为set x {foo bar}set x [list foo bar]调用,我们会得到正确数量的参数。

在其他时候,我们在列表中打包了一堆值,但是命令要求每个值都在它自己的参数中(您的max命令就是一个例子)。 ::tcl::mathfunc::max {2 3 1}失败,因为命令识别出它已被赋予单个值,并且该值应符合双精度浮点数的格式。在这种情况下,我们对列表中的值进行近似反演:我们将列表解压缩为参数。对于翻译来说,::tcl::mathfunc::max {*}{2 3 1}与编写::tcl::mathfunc::max 2 3 1一样有效。

(如果foo是零个或一个项目的列表,set x {*}$foo将始终有效。请考虑一下。)

max命令作为expr表达式中的函数调用是另一种蠕虫。一般来说,使用expr更简单,固定的表达式(例如expr {max($a,$b)})并找到f.i.(imho)会更好。通过调用命令而不涉及expr来获取列表的最大值。