如何阅读prolog中的谓词

时间:2016-04-24 17:32:21

标签: prolog logic

在学习命题逻辑和谓词逻辑后,我转向Prolog。

我想知道是否有人可以为我澄清语法,因为我无法阅读它。

我可以轻松阅读下面的内容。所以它是在说

  

如果X是Y的孩子,则X是Y的下降。

然后继续说

  

如果X是Z的子节点,Z是Y的下降,则X是Y的下降。

descend(X,Y) :-
   child(X,Y).
descend(X,Y) :-
   child(X,Z),
   descend(Z,Y).

但是一旦我开始研究列表编程,我就很难阅读谓词的语法。例如下面的

remove([], _, []).
remove([X | Xs], X, Ys) :- remove(Xs, X, Ys).
remove([Y | Xs], X, [Y | Ys]) :- X \== Y, remove(Xs, X, Ys).

从测试开始,它会移除第二个项目,例如,如果我输入

remove([a,b,c], b, Ys).

我会得到Ys = [a,c].

但我不知道如何阅读语法,如果有人可以为我分解,那就太好了。

2 个答案:

答案 0 :(得分:4)

由于您有一些逻辑背景,您可能会发现将规则作为逻辑公式阅读会很有帮助。让我们用dif / 2替换(\ ==)/ 2然后删除/ 3读取如下:

remove([], _, [])true

remove([X | Xs], X, Ys)remove(Xs, X, Ys)

remove([Y | Xs], X, [Y | Ys])dif(X,Y)remove(Xs, X, Ys)

注意暗示箭头如何指向规则的头部。这意味着规则的主体是先行者,规则的主体是结果。因此,您将规则读作:如果规则的主体为真,则规则的头部为真。规则中的目标通过结合连接。请注意事实如何true为先行,意味着remove([], _, [])始终为真。另一方面,如果规则的主体为假,则规则失败,但如果另一规则的主体为真,则谓词可能仍然成功。如果所有其他规则的主体也是假的,则谓词失败。因此,为谓词设置多个规则构成逻辑或:如果rule1 OR rule2 OR rule3成功,谓词remove / 3会成功。

正如您特别要求语法一样,熟悉列表的头尾符号也是合适的。也就是说,您可以显式地编写列表的第一个元素,然后是列表构造函数|和列表的其余部分:

[1|Xs] ...列表以1开头,然后有一个休息

[1,2|Xs] ...列表以12开头,然后是休息

[X|Xs] ...列表至少有一个元素后跟一个休息

请注意列表元素如何用,分隔,而列表的其余部分用|分隔。 |之后的术语实际上是一个列表,也可以是一个空列表。以下是相等列表的一些示例:

[1][1|[]]

相同

[1,2] = [1|[2]] = [1|[2|[]]] = [1,2|[]]

对于以下列表,已有8种方法可以编写它:

[1,2,3] = [1,2|[3]] = [1|[2,3]] = [1|[2|[3|[]]]] = ...

考虑到上述观察结果,您将逐个检查规则。由于@lurker在答案中已经这样做了,所以我不会详细介绍。但是,我想补充一点,如果一个规则有几个目标,比如你的例子中的第三个规则,我发现一次一个地完成目标是有帮助的:

remove([Y | Xs], X, [Y | Ys]) :-

原始列表的元素Y也在没有X IF的列表中...

remove([Y | Xs], X, [Y | Ys]) :-
   dif(X,Y),

... XY AND ...

不同
remove([Y | Xs], X, [Y | Ys]) :-
   dif(X,Y),
   remove(Xs, X, Ys).

......此关系也适用于XsXYs

那为什么要更换?内置谓词(\ ==)/ 2只是成功或失败,没有统一或副作用。它适用于在给定时间测试术语不等式,但以后没有任何影响。请考虑以下查询:

   ?- X=Y, X\==Y.
no

首先,变量XY是统一的,随后对不等式的测试失败。但是:

   ?- X\==Y, X=Y.
X = Y

首先,对不平等的测试成功,否则Prolog甚至不会考虑第二个目标。然后XY成功统一。这就是我的意思以后没有效果。所以我在上面写的关于读取谓词的所有内容对于(\ ==)/ 2并没有多大意义。

作为较短的版本,我使用if_/3=/3在帽子中抛出以下内容:

list_without_element([],[],_E).
list_without_element([X|Xs],L,E) :-
   if_(X=E,L=Ys,L=[X|Ys]),
   list_without_element(Xs,Ys,E). 

答案 1 :(得分:2)

你需要对它进行测试只是为了看它的作用,这说明remove/3可能不是那么好。 remove非常通用,并留下了“删除内容?”的问题。此外,它是命令式,而Prolog希望成为关系型。或许更好的名称是list_without/3,它表示第三个参数中的列表是第一个参数中的列表,但没有第二个参数。

尽管如此,让我们阅读你的内容。

阅读remove/3谓词可以按如下方式进行:

remove([], _, []).
  

如果删除任何元素,空列表仍然是空列表。

remove([X | Xs], X, Ys) :- remove(Xs, X, Ys).
  

列表Ys是已移除[X|Xs]元素的列表X 如果 Ys是删除所有X后的列表Xs来自remove([Y | Xs], X, [Y | Ys]) :- X \== Y, remove(Xs, X, Ys). 的1}}元素。

[Y|Ys]
  如果 [Y|Xs]X不同,那么

X是已删除Y元素的列表YsX {1}}是从Xs移除所有preg_match('/([A-Z]{2}[0-9]{3})/', $albumid) 元素后获得的列表。

作为练习,您应该再次尝试阅读这些内容,但请使用更多关系名称,例如我提供的示例重命名。