Prolog 通过尾部插入列表中的数字

Prolog Insert the number in the list by the tail

如何在 prolog 中构建一个谓词来接收一个数字和一个列表,我必须将数字插入列表的尾部

我试过从头插入列表中的数字:insert(H,[P|Q],[H,P|Q]). 并且有效,但是我怎样才能从尾插入数字?

可以使用两部分递归规则在尾部插入:

  • 当列表为空时,将结果统一为单元素列表,并插入项
  • 当list不为空时,将结果统一到一个head后面跟一个tail插入到tail的结果

英文说明比 Prolog 等效说明长得多:

ins_tail([], N, [N]).
ins_tail([H|T], N, [H|R]) :- ins_tail(T, N, R).

Demo.

只需像这样使用append/3

?- append([a,b,c,d],[x],List).
List = [a,b,c,d,x].

还没有人谈论 difference lists

差异列表

差异列表表示为 L-E,这只是一对由列表 L 组成的一对方便的符号,其最后一个 cons-cell 的尾部有 E

L = [ V1, ..., Vn | E]

空差异列表是 E-EE 是一个变量。每当你想优化列表时,你统一 E 。 比如要添加一个元素X,可以统一如下:

E = [X|F]

然后,L-F是新的列表。同样,您可以在恒定时间内追加列表。如果您将 F 与 "normal" 列表统一,特别是 [],您将关闭您的开放式列表。在所有操作期间,您通过 L 保留对整个列表的引用。当然,你仍然可以在L前面添加元素,使用通常的[W1, ..., Wm |L]-E符号。

是否需要差异列表是另一个问题。如果在末尾添加一个元素对您来说是一个有效的常见操作,并且如果您正在处理大型列表,它们就会很有趣。

定子句语法

DCG 是在 Prolog 中编写语法规则的便捷方式。它们通常作为 reader 宏实现,将 --> 形式转换为实际谓词。由于语法的目的是在解析过程中构建结构 (a.k.a.productions),因此实际谓词的翻译涉及差异列表。因此,尽管这两个概念在理论上是无关的,但差异列表通常是 DCG 的构建 material。

维基百科上的示例开头为:

 sentence --> noun_phrase, verb_phrase.

... 翻译为:

 sentence(S1,S3) :- noun_phrase(S1,S2), verb_phrase(S2,S3).

语法提供了很多"plumbing"(有点像monads)。 sentence/2 "built" 的对象是 S1,它是由谓词连接在一起的不同部分构成的。 S1 被传递给 noun_phrase,builds/extends 它是必要的,"returns" S2,它可以被视为 "whatever extends S1"。该值被传递给 verb_phrase,更新它并给出 S3、a.k.a。任何扩展 S2S3sentence 的一个参数,因为它也是 "whatever extends S1",给定我们的规则。 但是,这是Prolog,所以S1S2S3不一定是inputsoutputs,整个过程是统一的,回溯也有回溯(可以解析歧义语法) .他们最终与列表统一。

当我们遇到箭头右侧的列表时,差异列表开始发挥作用:

det --> [the].

以上规则翻译为:

det([the|X], X).

这意味着 det/2 将其第一个参数与一个尾部为 X 的开放式列表统一;其他规则统一 X。通常,您会发现与 [].

关联的 epsilon 规则

以上所有都是用宏完成的,一个典型的错误是试图在你的数据上调用一个辅助谓词,但失败了,因为转换添加了两个参数(对 helper(X) 的调用实际上是一个呼叫 helper(X,V,W))。您必须用大括号 { ... } 将实际主体括起来,以避免将谓词视为规则。

这是另一个选项。

insert(N,[],[N]).
insert(N,[H|T],[H|Q]) :- conc([H|T],[N],[H|Q]).
conc([],L,L).
conc([H|T],L,[H|Q]) :- conc(T,L,Q).