9

我正在阅读这个问题的答案,

p(X) :- read(A), q(A,X-[]).

q(end,X-X) :- !.    
q(A,[A|X]-Y) :- read(B), q(B,X-Y).

上面的代码使用语法List-List。我有点理解发生了什么,但我想知道“-”符号/谓词在这里究竟做了什么。另外,这个 SWI 是特定的吗?

4

2 回答 2

6

(-)/2表示差异列表是一个相当不常见的约定。在较旧的书中,(\)/2也使用了另一个运算符。

许多人更喜欢使用两个单独的参数。与使用运算符相比,有几个优点:

  1. 谓词不能意外地与参数的未实例化变量一起使用。考虑调用q(A, X)代替q(A, X-[]).

  2. 使用两个参数时,执行效率甚至更高。许多系统,如 SWI,必须(-)/2动态创建每个结构。

不过,还有另一种使用差异列表的方法,这种方法通常不太容易出错:您可以为此目的使用

实际上,程序有两个错误,其中一个是差异列表的处理方式造成的。另一个错误是程序不处理文件结尾。end_of_file代替.使用会更好end。但这是一件肤浅的事情,你迟早会发现自己。

另一个更细微的错误是由于差异列表和剪辑之间的相互作用造成的。我不是削减的忠实粉丝,但让我们看看这条规则。在其左侧的所有内容都已执行后进行剪切。

q(end_of_file,X-X) :- !.

第一个参数是 atom end_of_file。由于我们q/2只使用作为第一个参数的结果read/1,这只能是一个比较。所以我们在文件(或流)的末尾。然而,还有更多的事情必须坚持。只有当它们也成功时,才会执行剪切:第二个参数必须是 a (-)/2(好吧,在所有地方都有一个减号)。然后: 的两个参数(-)/2必须相同(必须统一)。为什么?我们在文件的末尾,但如果这些参数不统一,将尝试另一个规则。

这什么时候发生?这是一个令人讨厌的案例:

p([X,Y,Z]).

只需输入一个常数,比如说my_constant.然后按Cntrl-dCntrl+zp/1在这种情况下应该怎么办?理想情况下,它会在您完成输入后失败。但是,它将等待进一步的输入。

原因是切口放置不当。p/1我们说不坚定。这是 Prolog 程序中的常见错误。我只能建议减少削减的使用和 DCG 的采用。使用 DCG,这不会发生:

p2(X) :- read(A), phrase(q2(A),X).

q2(end_of_file) --> !.
q2(A) --> [A], {read(B)}, q2(B).

对于 DCG,无论 的参数如何,都会执行剪切p/1

于 2013-03-17T00:40:24.440 回答
2

我以为你的意思是:-。

这是一个差异列表。

http://en.wikibooks.org/wiki/Prolog/Difference_Lists

于 2013-03-17T00:02:36.360 回答