您可以通过翻转递归调用中的前两个参数来描述这种关系,正如 cmets 中的 @WillNess 所建议的那样。由于这两个列表的长度可能不同,因此拥有一个描述列表的谓词会很有帮助,以避免匹配非递归规则中的任意项。最好有一个更具描述性的名称来反映谓词的关系性质。考虑到所有这些,谓词可能看起来像这样:
islist([]).
islist([_|T]) :-
islist(T).
list_list_interlocked([],L,L) :-
islist(L).
list_list_interlocked([X|Xs],Ys,[X|Zs]) :-
list_list_interlocked(Ys,Xs,Zs).
您的示例查询按预期工作:
?- list_list_interlocked([1,2,3,4,5,6],[a,b,c],Zs).
Zs = [1, a, 2, b, 3, c, 4, 5, 6].
如果第二个列表更长,谓词也可以:
?- list_list_interlocked([1,2,3],[a,b,c,d,e,f],Zs).
Zs = [1, a, 2, b, 3, c, d, e, f].
而且它只适用于列表:
?- list_list_interlocked(definitelynolist,[],Zs).
false.
?- list_list_interlocked([],definitelynolist,Zs).
false.
后者是您需要islist/1 的原因。如果你像这样定义非递归规则:list_list_interlocked([],L,L).,那么 Prolog 可以将任意术语与L 统一起来,查询将产生不正确的结果:
?- list_list_interlocked([],definitelynolist,Zs).
Zs = definitelynolist.
谓词也可以用于其他方向,例如哪些列表在联锁时产生[1,a,2,b,3,c]?:
?- list_list_interlocked(X,Y,[1,a,2,b,3,c]).
X = [],
Y = [1, a, 2, b, 3, c] ;
X = [1, a, 2, b, 3, c],
Y = [] ;
X = [1],
Y = [a, 2, b, 3, c] ;
X = [1, 2, b, 3, c],
Y = [a] ;
X = [1, 2],
Y = [a, b, 3, c] ;
X = [1, 2, 3, c],
Y = [a, b] ;
X = [1, 2, 3],
Y = [a, b, c] ;
false.