子句头部的算术运算

Arithmetic operations in the head of a clause

我正在编写 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.

为什么我无法得到答案 'West.' 或任何其他答案?

原因是默认情况下 Prolog 不解释 +- 和其他算术运算符。 1+1 就是 1+1(这是 +(1,1) 的语法糖), 而不是 2。例如,如果您想要定义自己的表达式计算器,并且您将 + 视为布尔总和或完全不同的东西,这可能很有用。

然而,有一种方法可以 折叠 这样的表达式,这样它就可以使用 (is)/2 谓词从 1+1 派生出 2。例如:

turn_to_east(NX,Y) :-
    myPosition(X,Y),
    NX is X+1,
    write('East.').

假设您使用 turn_to_east(1,2)NX = 1 查询 turn_to_east/2。现在您获取 myPosition/2 数据:X = 2Y = 2。 Prolog 同时进行等价性检查,发现 turn_to_east/2 的 Y 坐标与 myPosition 的 Y 坐标相同。接下来它将 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 这样的副作用:这不仅适用于 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 变体进行计算。