7

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

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

?- 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 .
4

3 回答 3

2

次要点:它(^)/2不是^/2表示^用作运算符并使其有效的Prolog语法和谓词指示符(7.1.6.6)。

(**)/2(^)/2都是可评估函子 (9),因此它们可以用于与 的算术评估 (8.7) 和(is)/2与 的算术比较 (8.7)(=:=)/2(<)/2。它们的定义略有不同。

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

?- 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会给出带有两个整数参数的实值(如2^ -1)的情况下,会产生类型错误,然后对于其他复杂或未定义的结果会产生更多错误。

(^)/2很长一段时间以来一直用于求幂。指数运算符的早期使用是在 DHD Warren 的 1977 年论文中的符号微分示例中。(至少在 Philippe Roussel 1975 年的手册中没有提及)。在整个论文和 1978 年的用户指南中,该~字符始终如一地使用,^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

从 1982 年开始,它被用于量化setof/3bagof/3在自然语言解析器中用作 lambdas。对于所有这些用途,它已经具有正确的关联性和优先级。作为一个可评估的函子,它存在于几个系统中。

第一个(^)/2用作可评估函子的系统可能是 C-Prolog。

与这种传承相比,(**)/2Prolog 中出现的相对较晚,很可能是受到 Fortran 的启发。在第一次委员会草案(CD 1992)之前不久,它被提议纳入(N80 1991-07,巴黎论文)。系统也将其提供为exp/2.

(**)/2具有相同的优先级,(^)/2但没有任何关联性,起初可能会觉得很奇怪,因为在相当多的情况下,通常会进行两次幂运算。最突出的是,最简单形式的高斯函数

e -x 2

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

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

与其他系统相比,提供两种幂运算似乎很常见。^想想有和的 Haskell **

总结:似乎并不常见需要嵌套浮点取幂的情况。因此,最少的支持似乎更可取。

于 2014-12-11T01:52:22.077 回答
2

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

您给出的示例是由于以下差异:

?- integer(-1).
true.

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

以及以下优先级:

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

?- current_op(X, fy, -).
X = 200.
于 2014-12-11T06:51:45.570 回答
1

不一致的原因(不是理由)是,在 1995 年的原始标准中,只有**/2算术指数运算符,而^/2仅用于量化bagof/3和中的变量setof/3。对于后一种用途,具有右关联性是有意义的,因此您可以编写X^Y^foo(X,Y,Z). Why **/2is not given xfyassociativity I don't know(例如,它与 Fortran 一致)。

^/22012 年的“更正”中添加了 as 指数运算符,而没有修改语法,导致当前的不一致。

但请注意,您可以通过添加指令来简单地解决这个问题

:- op(200, xfy, **).

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

于 2014-12-10T22:55:29.353 回答