这是一个将两个列表附加在一起的算法:
Domains
list= integer*
Predicates
nondeterm append(list, list, list)
Clauses
append([], List, List) :- !.
append([H|L1], List2, [H|L3]) :- append(L1, List2, L3).
Goal
append([9,2,3,4], [-10,-5,6,7,8], Ot).
结果是一个列表[9,2,3,4,-10,-5,6,7,8]
,它保存在“Ot
”中。
我的问题是,这是如何运作的?
我理解的是,在每个递归调用中,在第一个列表中,您只将尾部作为列表(因此将其大小减小1
直到它为[]
),第二个参数“ List2
“根本没有变化,第三个参数......起初它是[]
,并且在每次递归调用之后都会得到它的尾部,但是因为它是[]
,它会保持[]
{1}}。
那么,为什么突然,在第三个参数(“Ot
”)中我们有附加列表?
有人可以一步一步地解释这个算法吗?
答案 0 :(得分:12)
首先,让我们将这些条款翻译成更容易理解的内容:
append([], List, List) :- !.
可以写
append([], List2, Result) :-
Result = List2,
!.
和
append([H|L1], List2, [H|L3]) :- append(L1, List2, L3).
可以写
append(List1, List2, Result) :-
List1 = [Head1 | Tail1],
Result = [HeadR | TailR],
Head1 = HeadR,
append(Tail1, List2, TailR).
我希望这对你来说已经更清楚了。
然后,一步一步地,数字表示每次使用的子句,并显示结果调用:
append([9, 2, 3, 4], [-10, -5, 6, 7, 8], Ot).
|
2
|
` append([2, 3, 4], [-10, -5, 6, 7, 8], Ot'). % and Ot = [9|Ot']
|
2
|
` append([3, 4], [-10, -5, 6, 7, 8], Ot''). % and Ot' = [2|Ot'']
|
2
|
` append([4], [-10, -5, 6, 7, 8], Ot'''). % and Ot'' = [3|Ot''']
|
2
|
` append([], [-10, -5, 6, 7, 8], Ot''''). % and Ot''' = [4|Ot'''']
|
1
|
` Ot'''' = [-10, -5, 6, 7, 8]
在此步骤中,我们已经定义了所有我们感兴趣的值。注意结果的头部是如何设置之前它的尾部被后续(尾部递归)调用append
填充,构建结果列表Prolog自上而下时尚的特征(也称为"tail recursion modulo cons")。
让我们按照定义来看看Ot
是什么,在最后一步:
Ot = [9|Ot']
Ot' = [2|Ot'']
Ot'' = [3|Ot''']
Ot''' = [4|Ot'''']
Ot'''' = [-10, -5, 6, 7, 8]
Ot''' = [4, -10, -5, 6, 7, 8]
Ot'' = [3, 4, -10, -5, 6, 7, 8]
Ot' = [2, 3, 4, -10, -5, 6, 7, 8]
Ot = [9, 2, 3, 4, -10, -5, 6, 7, 8]
我希望你能从中获得一些东西。
答案 1 :(得分:2)
让我们将Prolog翻译成英文。我们有两条规则:
将List
追加到[]
的结果是List
。
将任何List
附加到第一个元素为H
且余数为L1
的列表的结果等于其第一个元素也为H
的列表其余部分是将List
附加到L1
。
因此,我们要将[-10,-5,6,7,8]
追加到[9,2,3,4]
。附加的列表不为空,因此我们可以跳过该规则。根据第二条规则,结果将9
作为第一个元素,然后将[-10,-5,6,7,8]
附加到[2,3,4]
的结果。
因此,我们要将[-10,-5,6,7,8]
追加到[2,3,4]
。附加的列表不为空,因此我们可以跳过该规则。根据第二条规则,结果将2
作为第一个元素,然后将[-10,-5,6,7,8]
附加到[3,4]
的结果。
因此,我们要将[-10,-5,6,7,8]
追加到[3,4]
。附加的列表不为空,因此我们可以跳过该规则。根据第二条规则,结果将3
作为第一个元素,然后将[-10,-5,6,7,8]
附加到[4]
的结果。
因此,我们要将[-10,-5,6,7,8]
追加到[4]
。附加的列表不为空,因此我们可以跳过该规则。根据第二条规则,结果将9
作为第一个元素,然后将[-10,-5,6,7,8]
附加到[]
的结果。
因此,我们要将[-10,-5,6,7,8]
追加到[]
。附加的列表为空,因此根据第一条规则,结果为[-10,-5,6,7,8]
。
由于将[-10,-5,6,7,8]
追加到[]
的结果为[-10,-5,6,7,8]
,因此将[-10,-5,6,7,8]
追加到[4]
的结果为[4,-10,-5,6,7,8]
。
由于将[-10,-5,6,7,8]
追加到[4]
的结果为[4,-10,-5,6,7,8]
,因此将[-10,-5,6,7,8]
追加到[3,4]
的结果为[3,4,-10,-5,6,7,8]
。
由于将[-10,-5,6,7,8]
追加到[3,4]
的结果为[3,4,-10,-5,6,7,8]
,因此将[-10,-5,6,7,8]
追加到[2,3,4]
的结果为[2,3,4,-10,-5,6,7,8]
。
由于将[-10,-5,6,7,8]
追加到[2,3,4]
的结果为[2,3,4,-10,-5,6,7,8]
,因此将[-10,-5,6,7,8]
追加到[9,2,3,4]
的结果为[9,2,3,4,-10,-5,6,7,8]
。