【问题标题】:Arithmetic operations in the head of a clause子句头部的算术运算
【发布时间】:2015-12-13 02:24:20
【问题描述】:

我是一个写作 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 不像其他语言。它没有返回值的函数。它具有成功、失败或不终止(坏)的谓词。而且它不做 in-line 表达式评估。所以 turn_to_west(X-1,Y) 例如不会将 X 递减 1。
  • 首先是一些术语:在Prolog中,没有函数,这些是谓词

标签: prolog logic-programming


【解决方案1】:

原因是默认情况下 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 变体进行计算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多