在下面的代码中,我不确定前三行是做什么的?我理解第四行递归地取消了List 1和List2,但为什么需要上面的规则呢?
interweave([],[],[]).
interweave([X],[],[X]).
interweave([],[Y],[Y]).
interweave([X|List1],[Y|List2],[X,Y|Result]) :-
interweave(List1,List2,Result).
答案 0 :(得分:2)
在Prolog中,您可以在不查看实际代码的情况下回答这些问题!只需询问最常见的查询:
| ?- interweave(Xs,Ys,Zs).
Xs = [],
Ys = [],
Zs = [] ? ;
Xs = [_A],
Ys = [],
Zs = [_A] ? ;
Xs = [],
Ys = [_A],
Zs = [_A] ? ;
Xs = [_A],
Ys = [_B],
Zs = [_A,_B] ?
所以这些案例都包含在内:如果两个列表都是空的,或者其中只有一个列表只包含一个元素。
答案 1 :(得分:2)
正如其他人所指出的,当你有一个递归谓词条款,如:
interweave([X|List1], [Y|List2], [X,Y|Result]) :-
interweave(List1, List2, Result).
您需要终止案例。否则,逻辑在哪里结束?在这种情况下,只要前两个参数都是至少一个元素的列表(或者可以有效地实例化),第三个参数是至少两个元素的列表(或者可以实例化) ,然后会发生递归。
当您为前两个参数传递列表并期望第三个参数中的结果时,最终您将遇到下列情况之一,这将使上述谓词子句失败:
1. interweave([], List2, Result), where List2 has at least one element
2. interweave(List1, [], Result), where List1 has at least one element
3. interweave([], [], Result)
由于[X|T]
无法与[]
统一,因此所有这三种情况都会使上述谓词条款失败。它必然是至少一个元素的列表。因此,如果没有基本情况,如果任何参数被完全实例化,则整个谓词都会失败,或者如果它们都没有,则会无限递归。
因此,您需要至少一个基本案例才能成功。但基本情况应该是什么?这取决于你对谓词的期望。在原始实现的情况下,基本案例会给您以下行为:
1)当两个原始输入列表的长度相同时,interweave([], [], []).
会成功。
2)interweave([X], [], [X]).
在第一个列表只有一个元素而不是第二个列表时启用成功。
3)interweave([], [Y], [Y]).
在第二个列表中只有一个元素而不是第一个列表时启用成功。
interweave([1,2,3], [a,b,c], R). % R = [1,a,2,b,3,c]
interweave([1,2,3], [a,b], R). % R = [1,a,2,b,3]
interweave([1,2], [a,b,c], R). % R = [1,a,2,b,c]
但是,以下情况会失败:
interweave([1,2,3], [a], R).
interweave([1], [a,b,c], R).
etc
您可以通过多种方式更改此行为。例如,如果要求两个输入列表的长度相同,则省略基本情况#2和#3。如果您希望将任何长度的列表“编织”在一起并且只是追加额外的元素,那么您可以将基本案例更改为:
interweave([], L, L).
interweave(L, [], L).
这些说与另一个列表L
编织在一起的空列表是列表L
。由于[]
是一个列表,因此您可以interweave([], [], [])
成功,而无需明确说明。但是,对于interweave([], [], []).
,它将成功两次,因此在某些情况下会产生一些重复的结果。为避免这种情况,您可以将这些基本案例定义为:
interweave([], L, L).
interweave(L, [], L) :- L = [_|_]. % Only true for non-empty list L
答案 2 :(得分:1)
当您编写递归过程时,通常会指定所谓的“基本案例”,即当不再需要或可能再次调用该过程时该怎么做。
因此,这3条规则指定了交织/ 3的基本情况。整个过程的高级描述可以读取(但事实上,我发现Prolog代码更清晰:)
交织(List1,List2,Result):结果按顺序放置List1和List2的所有元素。 List1和List2 的长度必须最多为1。