Prolog 子句开头的算术运算

Prolog 子句开头的算术运算,prolog,logic-programming,Prolog,Logic Programming,我是一个编写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), wri

我是一个编写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。例如,如果您想定义自己的表达式计算器,并且您将
+
视为布尔和或完全不同的东西,那么这可能非常有用

但是,有一种方法可以折叠这样的表达式,使其使用谓词从
1+1
派生出
2
。例如:

turn_to_east(NX,Y) :-
    myPosition(X,Y),
    NX is X+1,
    write('East.').
如果您使用
转向东(1,2)
查询
转向东(1,2)
NX=1
。现在获取
myPosition/2
数据:
X=2
Y=2
。Prolog同时进行了等价性检查,发现
转向东/2
的Y坐标与
myPosition
的Y坐标相同。接下来,它将
2+1
折叠为
3
,并发现这并不等同于
NX=1
,因此该谓词失败。但是,如果您查询了
转向东(3,1)
,它就会成功,从而写入
东。

如果您使用上述概念修改整个理论,如:

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\u-to\u-point/2
谓词显然是一个交互谓词,而它的
turn\u-to\u-point/3
变体进行计算。

Prolog与其他语言不同。它没有返回值的函数。它有成功、失败或不终止(坏)的谓词。而且它不进行在线表达式求值。所以
turn_to_west(X-1,Y)
例如,不会将
X
减量1。首先是一些术语:在Prolog中,没有函数,这些是谓词。