结构(差异列表)Prolog

5
这个问题涉及书籍《Prolog程序设计》第三章的内容,作者是Clocksin和Mellish,第五版。
在该书第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. 在哪些情况下最好使用每种表示方式?

谢谢


感谢大家的有益评论。 - Karl 17302
3个回答

7

一定不要使用(-)/2或者(\)/2或任何其他运算符代表“差分列表”。 这是因为你经常会遇到一个谓词只有一个列表参数并且内部谓词使用了差分列表,两者都具有相同的元数,可能也具有相同的名称,这会使事情变得混乱。 更糟糕的是,它可能在“某些情况”下起作用。 此外,该运算符将产生一些成本,您可以通过使用两个单独的参数来避免这些成本。

尽量坚持干净明了的命名约定。 使用 S0S1 ... S 可以轻松识别表示差分列表的参数。 为了更好地强调这些参数属于一起,有些人在逗号分隔符后面不使用空格,而对于其他参数则使用空格。 因此:

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

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

我所知道的任何一本介绍差分列表操作符的Prolog书籍都出自1980年代。


@Will:现在有真实的答案了! - false

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

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

实际上,不是一个复合术语持有两个列表在一个单一的参数,而是两个参数,这应该是一个更有效的表示。

编辑

确保阅读@false的答案。


6

我同意Boris所说的关于不同表示法的观点(+1)。此外,在我看来,这显然是一个应该使用DCGs而不是明确编码列表差异的案例。例如,考虑以下版本的代码:

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具有清晰的声明性和易于阅读的解释,并且需要较少的参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接