我正在阅读this问题的答案,
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是否具体?
答案 0 :(得分:6)
代表差异列表的(-)/2
是一种相当罕见的惯例。在旧书中,也使用了另一个运算符(\)/2
。
许多人更喜欢使用两个单独的参数。与使用运算符相比,有几个优点:
谓词不能意外地与参数的未实例化变量一起使用。考虑调用q(A, X)
代替q(A, X-[])
。
使用两个参数时,执行效率更高一些。许多系统(如SWI)必须动态创建每个(-)/2
结构。
尽管如此,还有另一种方法可以使用差异列表,这通常不易出错:您可以使用dcg来实现此目的。
实际上,程序中有两个错误,其中一个错误是由差异列表的处理方式引起的。另一个错误是程序不处理文件结束。最好使用end_of_file
代替end
。但这是一个你迟早会发现自己的肤浅的东西。
另一个更微妙的错误是由于差异列表和剪切之间的相互作用。我不是削减的忠实粉丝,但让我们看看这条规则。在左侧的所有东西都被执行后切割。
q(end_of_file,X-X) :- !.
第一个参数是原子end_of_file
。由于我们仅使用q/2
作为第一个参数的read/1
结果,因此这只能是一个比较。所以我们在文件(或流)的末尾。然而,还有其他事情必须坚持下去。只有那些成功的人才会被执行:第二个参数必须是(-)/2
(好的,在所有地方都有一个减号)。然后:(-)/2
的两个参数必须相同(必须统一)。为什么?我们在文件的末尾,但如果这些参数没有统一,那么将尝试另一个规则。
这是什么时候发生的?这是一个令人讨厌的案例:
p([X,Y,Z]).
只需输入一个常量,例如my_constant.
,然后按 Cntrl-d 或 Cntrl + z 。 p/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
的参数如何,都会执行剪切。
答案 1 :(得分:2)