我是一个编写 Prolog 谓词,它将笛卡尔坐标系中的某个点 (myPosition(2,2)
) 与附近的其他点进行比较。因此,它应该显示我们应该选择从 myPosition(2,2)
到该点的方向(北、东、南、西)。这是我的 .pl
文件的代码:
myPosition(2,2).
turn_to_east(X+1,Y) :-
myPosition(X,Y),
write('East.').
turn_to_west(X-1,Y) :-
myPosition(X,Y),
write('West.').
turn_to_north(X,Y+1) :-
myPosition(X,Y),
write('North.').
turn_to_south(X,Y-1) :-
myPosition(X,Y),
write('South.').
turn_to_the_point(X,Y) :- turn_to_east(X,Y).
turn_to_the_point(X,Y) :- turn_to_west(X,Y).
turn_to_the_point(X,Y) :- turn_to_north(X,Y).
turn_to_the_point(X,Y) :- turn_to_south(X,Y).
然后,当我将文件上传到 SWI-Prolog 并写入时:
turn_to_the_point(1,2).
我得到的是:
false.
为什么我无法得到“西方”的答案。或任何其他?
最佳答案
原因是默认情况下 Prolog 不解释 +
, -
和其他算术运算符。 1+1
就是1+1
(这是 +(1,1)
的语法糖),不是 2。例如,如果您想定义自己的表达式计算器,并且您看到 +
,这可能很有用。作为 bool 总和,或者完全不同的东西。
但是,有一种方法可以折叠这样的表达式,使其派生 2
共 1+1
使用 (is)/2
谓词。例如:
turn_to_east(NX,Y) :-
myPosition(X,Y),
NX is X+1,
write('East.').
给定您的查询turn_to_east/2
与 turn_to_east(1,2)
, NX = 1
。现在您获取 myPosition/2
数据:X = 2
和Y = 2
。 Prolog 同时进行等价检查,发现 turn_to_east/2
的 Y 坐标与 myPosition
之一相同。接下来它崩溃了2+1
至3
并发现这不等于 NX = 1
所以这个谓词失败了。但如果您查询过turn_to_east(3,1)
它会成功并因此写 East.
.
如果您用上面讨论的概念修改您的整个理论,例如:
myPosition(2,2).
turn_to_east(NX,Y) :-
myPosition(X,Y),
NX is X+1,
write('East.').
turn_to_west(NX,Y) :-
myPosition(X,Y),
NX is X-1,
write('West.').
turn_to_north(X,NY) :-
myPosition(X,Y),
NY is Y+1,
write('North.').
turn_to_south(X,NY) :-
myPosition(X,Y),
NY is Y-1,
write('South.').
turn_to_the_point(X,Y) :- turn_to_east(X,Y).
turn_to_the_point(X,Y) :- turn_to_west(X,Y).
turn_to_the_point(X,Y) :- turn_to_north(X,Y).
turn_to_the_point(X,Y) :- turn_to_south(X,Y).
它正确回答了查询:
?- turn_to_the_point(1,2).
West.
true ;
false.
一般来说,谓词最好不要有副作用,如 write/1
stuff:这不仅适用于 Prolog,几乎所有编程语言都建议将程序分为计算和交互。也许解决这个问题的更好方法是将方向视为参数:
myPosition(2,2).
turn_to_point(NX,Y,east) :-
myPosition(X,Y),
NX is X+1.
turn_to_point(NX,Y,west) :-
myPosition(X,Y),
NX is X-1.
turn_to_point(X,NY,north) :-
myPosition(X,Y),
NY is Y+1.
turn_to_point(X,NY,south) :-
myPosition(X,Y),
NY is Y-1.
turn_to_the_point(X,Y) :-
turn_to_point(X,Y,D),
write(D).
在这种情况下 turn_to_the_point/2
谓词显然是一个交互谓词,而它的turn_to_the_point/3
变体进行计算。
关于prolog - 子句开头的算术运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34242509/