为什么**/2
(xfx
)和(^)/2
(xfy
)的参数优先级在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 .
答案 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中,运算符声明仅在模块中本地有效。