在处理列表时,Prolog中的" - "符号是什么意思?

ivt*_*ivt 9 prolog dcg difference-lists prolog-cut

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

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

q(end,X-X) :- !.    
q(A,[A|X]-Y) :- read(B), q(B,X-Y).
Run Code Online (Sandbox Code Playgroud)

上面的代码使用语法List-List.我有点理解发生了什么,但我想知道" - "符号/谓词到底是做什么的.此外,这个SWI是否具体?

fal*_*lse 6

(-)/2代表差异表是一个相当罕见的约定.在旧书中,(\)/2也使用了另一个操作员.

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

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

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

尽管如此,还有另一种方法可以使用差异列表,这通常不易出错:您可以使用来实现此目的.

实际上,程序中存在两个错误,其中一个错误是由差异列表的处理方式引起的.另一个错误是程序不处理文件结束.最好用end_of_file它代替end.但这是一个你迟早会发现自己的肤浅的东西.

另一个更微妙的错误是由于差异列表和剪切之间的相互作用.我不是削减的忠实粉丝,但让我们看看这条规则.在左侧的所有东西都被执行后切割.

q(end_of_file,X-X) :- !.
Run Code Online (Sandbox Code Playgroud)

第一个参数是原子end_of_file.由于我们仅使用第一个参数q/2的结果read/1,因此这只能是比较.所以我们在文件(或流)的末尾.然而,还有其他事情必须坚持下去.只有那些成功的人才会被执行:第二个论点必须是(-)/2(好的,在所有地方都有一个减号).然后:两个论点(-)/2必须相同(必须统一).为什么?我们位于文件的末尾,但如果这些参数不统一,则会尝试其他规则.

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

p([X,Y,Z]).
Run Code Online (Sandbox Code Playgroud)

只需输入一个常量,my_constant.然后按Cntrl-dCntrl+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).
Run Code Online (Sandbox Code Playgroud)

使用DCG,无论参数如何,都会执行剪切p/1.