我无法理解下面的代码。
有人可以解释一步一步发生了什么,如果我有后续输入:遵循prolog代码做什么?
append([1,2,3], Lst).
其实,我不;吨得到怎样1,2附加列表LST结果。
append([_], []).
append([H|T], [H|N]) :- append(T,N).
我无法理解下面的代码。
有人可以解释一步一步发生了什么,如果我有后续输入:遵循prolog代码做什么?
append([1,2,3], Lst).
其实,我不;吨得到怎样1,2附加列表LST结果。
append([_], []).
append([H|T], [H|N]) :- append(T,N).
这听起来像你是Prolog的新手。如果是这样,欢迎!我们来分析一下。
这个不幸命名的函数有两个子句。 Prolog查看这些条款以查看哪一个适用。当它找到一个匹配时,它会尝试执行它。如果在执行某个操作时出现故障,它将备份并尝试下一个选项。这些选择点恰恰根据程序而变化;在这个程序中,唯一一个将在子句级别,决定使用哪个规则。
查看第一条规则的一种方法是,它说“一个包含一个元素的列表,不管该元素是什么,都与空列表有关。”查看append([_], [])
,如果我们有X = [foo]
和Y = []
,它会持有,因为[foo]
是一项清单,而[]
是空白清单。这个规则是很好的Prolog风格,因为它不管实例化都可以工作:我们可以提供左边或右边,也可以不提供,不重要。
第二个条款也很简单。它说,如果左边的参数和右边的参数都以相同的项目开始,并且其余的列表也是由相同的谓词相关的,则左边的参数和右边的参数是相关的。换句话说,如果我有两个列表X
和Y
这样append(X, Y)
为真,那么append([H|X], [H|Y])
也是如此。不管H是什么,X和Y都是无关紧要的,除非append/2
暗示。
从逻辑上思考,如果我知道任何一个项目列表与空列表相关,并且任何列表都与以相同项目开头并且相同的列表相关,则唯一可以列出的列表如此相关的是每个项目都是相同的列表,除了左侧列表中最后有一个项目不在右侧。所以[1,2,3,4]与[1,2,3]有关,但[1,2,3,foo]和[1,2,3]也是如此。
在程序上,让我们来看看,因为这谓语用此组参数处理会发生什么:
append([1,2,3], X).
的第一条规则不匹配[1,2,3]。因此,我们必须看看第二条规则:
append([1|[2,3]], [1|X]) :- append([2,3], X).
我们可以重复:
append([2|[3]], [2|Y]) :- append([3], Y).
现在的第一条规则确实比赛:
append([3], []).
所以把他们放在一起:
append([1,2,3], [1|X]) implies
append([2,3], X=[2|Y]) implies
append([3], Y=[])
so Y = []
so X = [2]
so the right side is [1,2].
Prolog的跟踪将显示你基本上是相同的信息:
?- trace, append([1,2,3], X).
Call: (7) append([1, 2, 3], _G1633) ? creep
Call: (8) append([2, 3], _G1752) ? creep
Call: (9) append([3], _G1755) ? creep
Exit: (9) append([3], []) ? creep
Exit: (8) append([2, 3], [2]) ? creep
Exit: (7) append([1, 2, 3], [1, 2]) ? creep
是什么让这个Prolog的代码混淆的是,它并不像你告诉Prolog的如何做任何事情。事实并非如此,但通过指定逻辑上的真实性,Prolog能够自己弄明白。这是非常聪明的代码。如果这是Haskell,我们将讨论内置函数init
,它将返回除最后一项以外的所有列表。
希望这会有所帮助!
谢谢。这是非常有帮助的。 – Chaos 2013-02-28 19:27:18