5

这个问题参考了本书第 3 章中的材料:Programming in Prolog, Clocksin and Mellish, Ed 5

在本书的第 72 页中,显示了一个使用差异列表的程序:

partsOf(X,P):- partsacc(X,P,Hole) , Hole=[].

partsacc(X,[X|Hole],Hole):-basicpart(X).
partsacc(X,P,Hole):- assembly(X,Subparts), partsacclist(Subparts, P, Hole).

partsacclist([],Hole,Hole).
partsacclist([P|T], Total, Hole):- partsacc(P,Total,Hole1), partsacclist(T,Hole1,Hole).

在网上很多教程中,使用“-”的格式如下,例如:

append([ A , B , C | R1 ] – R1 , [ D , E | R2 ] – R2 , R3)

我的问题是:

  1. 这两种表示有什么区别(使用 - 和不使用它)

  2. 在哪些情况下最好使用它们中的每一个?

谢谢

4

3 回答 3

7

无论如何:不要使用(-)/2or(\)/2或任何其他运算符来表示“差异列表”。原因是您通常会有一个带有一个列表参数的谓词和一个使用差异列表的内部谓词。由于两者具有相同的数量并且可能也具有相同的名称,事情会变得混乱。更糟糕的是,它可能适用于“某些情况”。此外,该运算符会产生一些成本,您可以使用两个单独的参数来避免。

尝试坚持干净的命名约定。也就是说S0S1…… S_ 以这种方式,表示差异列表的参数将很容易看到。为了更好地强调这些论点属于一起,有些人在分隔逗号后不使用空格,而将其用于其他论点。因此:

p(L+R, S0,S) :-
   p(L, S0,S1),
   p(R, S1,S).

此外,(-)/2在 Prolog 中还有另一个含义。它用于表示一对Key-Value,如keysort/2

我所知道的任何建议使用差异列表运算符的 Prolog 书都来自 1980 年代。

于 2014-01-22T07:32:58.740 回答
6

我在 Prolog 中的经验有限,但似乎较旧的文本倾向于使用 the-或另一个字符(例如\)来表示列表及其尾部。较新的 Prolog 代码总是使用两个参数(如在您的第一个示例中)。例如,SWI-Prolog 中的所有内置谓词和库谓词始终使用两个单独的参数。

从理论上讲,您喜欢哪种风格没有区别。我想在你自己的代码中保持一致并没有什么坏处。

在实践中,不同之处在于,不是在一个参数中包含两个列表的复合术语,而是有两个参数,这应该是更有效的表示。

编辑

确保还阅读@false 的答案。

于 2014-01-21T19:51:10.310 回答
6

我同意鲍里斯关于不同表述的说法(+1)。此外,在我看来,这显然是您应该使用 DCG 而不是显式编码列表差异的情况。例如,考虑以下版本的代码:

parts(X) --> { basicpart(X) }, [X].
parts(X) --> { assembly(X, Parts) }, assembly_(Parts).

assembly_([])     --> [].
assembly_([X|Xs]) --> parts(X), assembly_(Xs).

用法,在定义后assembly/2并与basicpart/1您的示例完全相同:

?- phrase(parts(X), Ls).

DCG 具有清晰的声明性和易于阅读的解释,并且需要较少的参数。

于 2014-01-21T22:47:16.457 回答