结构(差异列表)Prolog

时间:2014-01-21 18:29:11

标签: prolog dcg difference-lists

这个问题涉及本书第3章的内容:  Prolog,Clocksin和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. 在哪种情况下最好使用它们?

  3. 由于

3 个答案:

答案 0 :(得分:7)

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

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

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

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

我知道的任何Prolog书都建议差异列表的运营商来自20世纪80年代。

答案 1 :(得分:6)

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

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

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

修改

请务必阅读@false的答案。

答案 2 :(得分:6)

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

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

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

用法,完全按照示例定义assembly/2basicpart/1之后:

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

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