由于**和^的运算符优先级不同而导致的轻微不一致

时间:2014-12-09 23:06:44

标签: prolog operator-precedence iso-prolog

为什么**/2xfx)和(^)/2xfy)的参数优先级在Prolog中不相同?

这会导致轻微的不一致,例如:

?- X = 1, Y is 1 ^ -X.
X = Y, Y = 1.

?- Y is 1 ** -1.
Y = 1.

但:

?- X = 1, Y is 1 ** -X.
ERROR: Syntax error: Operator priority clash
ERROR: X = 1, Y is 1 *
ERROR: ** here **
ERROR: * -X .

3 个答案:

答案 0 :(得分:2)

次要点:(^)/2而非^/2表示^用作运算符并使其成为有效的Prolog语法和谓词指标(7.1.6.6) )。

(**)/2(^)/2都是可评估的仿函数(9),因此它们可用于(is)/2的算术评估(8.7)和{{1}的算术比较(8.7) },(=:=)/2等。他们的定义略有不同。

(<)/2总是以与(**)/2总是给出浮点数相同的方式返回浮点数。 (SWI在这里没有遵循标准,它有自己的惯例)。

(/)/2

?- X is 2**2. X = 4.0. ?- X is 2/2. X = 1.0. 允许整数取幂,这对于现在支持任意大整数的许多系统来说变得更加重要。想想(^)/2。也就是说,如果两个参数都是整数,那么结果也是一个整数,就像2^2^X处理这种情况一样。

(*)/2

?- X is 2^2, Y is 2*2. X = 4, Y = 4. ?- X is 2.0^2, Y is 2.0*2. X = 4.0, Y = 4.0. 使用两个整数参数(如(^)/2)给出实际值的情况下,会产生类型错误,然后对于其他复杂或未定义的结果会有更多错误。< / p>

2^ -1用于求幂已有一段时间了。 指数运算符的早期使用在D.H.D.沃伦的1977年论文中的象征性分化。 (至少在Philippe Roussel的1975年手册中没有提及)。在整个论文和1978年的用户指南中,(^)/2字符被一致地使用,人们期望在~中有^,声明如下,自1982年以来没有变化。

integers are restricted to the range -2~17 to 2~17-1 , ie. -131072 to 131071.

从1982年起,它被用于量化:- op(300, xfy, ~). % 1977 :- op(200, xfy, ^). % 1982 - today setof/3,但也被用作自然语言解析器中的lambda。对于所有这些用途,它已经具有正确的关联性和优先级。作为一个可评估的函子,它存在于几个系统中。

使用bagof/3作为可评估函子的第一个系统意味着权力可能是C-Prolog。

与此遗产相比,(^)/2相对较晚出现在Prolog中,很可能是受到Fortran的启发。建议在第一份委员会草案(CD 1992)之前不久列入(N80 1991-07,巴黎论文)。系统也将其作为(**)/2提供。

exp/2具有与(**)/2相同的优先级,但没有任何关联性,最初可能会出现奇怪的现象,因为在某些情况下,两次取幂通常很常见。最突出的是Gaussian function最简单的形式

  

电子 -x 2

不是使用常数e和取幂,而是提供了一个特殊的可评估仿函数(^)/2。因此,上面写为exp/1。事实上,维基百科也使用这种表示法。鉴于这个仿函数,在这种常见情况下不需要关联性。

如果真的有,我会非常有兴趣看到它。

与其他系统相比,提供两种取幂似乎很常见。想想Haskell有exp(- X**2)^

总结:似乎不存在需要嵌套浮点运算的常见情况。所以最小的支持似乎更可取。

答案 1 :(得分:2)

@false回答了您的第一个问题。

您给出的示例是由于以下区别:

?- integer(-1).
true.

?- X = 1, integer(-X).
false.

以及以下优先顺序:

?- current_op(X, xfx, **).
X = 200.

?- current_op(X, fy, -).
X = 200.

答案 2 :(得分:1)

不一致的原因(不合理)是在1995年的原始标准中,只有**/2是算术取幂运算符,而^/2仅用于量化bagof/3中的变量和setof/3。对于后者的使用,它具有正确的相关性是有道理的,所以你可以写X^Y^foo(X,Y,Z).为什么**/2没有被赋予xfy关联性我不知道(它本来是与Fortran一致,例如)。

作为取幂运算符的^/2被添加到2012&#34;更正&#34;中,没有修改语法,导致当前的不一致。

但请注意,您可以通过添加指令

来自行解决此问题
:- op(200, xfy, **).

这不太可能导致任何问题。此外,在许多现代Prolog中,运算符声明仅在模块中本地有效。