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).
只需像这样使用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-E
,E
是一个变量。每当你想优化列表时,你统一 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。任何扩展 S2。 S3 是 sentence
的一个参数,因为它也是 "whatever extends S1",给定我们的规则。 但是,这是Prolog,所以S1,S2和S3不一定是inputs或outputs,整个过程是统一的,回溯也有回溯(可以解析歧义语法) .他们最终与列表统一。
当我们遇到箭头右侧的列表时,差异列表开始发挥作用:
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).
如何在 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).
只需像这样使用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-E
,E
是一个变量。每当你想优化列表时,你统一 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。任何扩展 S2。 S3 是 sentence
的一个参数,因为它也是 "whatever extends S1",给定我们的规则。 但是,这是Prolog,所以S1,S2和S3不一定是inputs或outputs,整个过程是统一的,回溯也有回溯(可以解析歧义语法) .他们最终与列表统一。
当我们遇到箭头右侧的列表时,差异列表开始发挥作用:
det --> [the].
以上规则翻译为:
det([the|X], X).
这意味着 det/2
将其第一个参数与一个尾部为 X
的开放式列表统一;其他规则统一 X
。通常,您会发现与 []
.
以上所有都是用宏完成的,一个典型的错误是试图在你的数据上调用一个辅助谓词,但失败了,因为转换添加了两个参数(对 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).