为什么我的 Prolog 谓词使用相同的绑定成功两次?

Avr*_*oel 2 prolog

抱歉,如果这是一个愚蠢的问题,但我仍处于学习 Prolog 的早期阶段(SWI-Prolog,以防它有所作为),并且可能会做一些愚蠢的事情。

我正在尝试编写一个谓词,weave/3如果第三个参数(列表)与将前两个参数编织在一起相同,则该谓词将会成功[*]。例如...

weave([1], [a], [1,a]).
weave([1,2], [a,b], [1,a,2,b]).
weave([1,2], [a,b,c,d], [1,a,2,b]).
Run Code Online (Sandbox Code Playgroud)

我的意图是,如果一个列表比另一个列表长(如第三个示例中所示),则多余的元素将被忽略。

我目前的尝试如下......

weave(_, [], []). % bail out if the first list is longer
weave([], _, []). % bail out if the second list is longer
weave([H1|T1], [H2|T2], Res) :-
  weave(T1, T2, Ts),
  append([H1, H2], Ts, Res).
Run Code Online (Sandbox Code Playgroud)

当第二个列表比第一个列表长时,这很好用......

weave([1,2], [a,b,c,d,e,f], Res).
Res = [1, a, 2, b].
Run Code Online (Sandbox Code Playgroud)

我得到了显示的一个绑定,并且执行结束。

如果第一个列表较长,我仍然获得正确的绑定,但需要按下按键;false结束执行...

weave([1,2,3,4], [a,b,c], Res).
Res = [1, a, 2, b, 3, c] ;
false.
Run Code Online (Sandbox Code Playgroud)

但是,如果列表的长度相同,那么我会得到正确的绑定,但是两次,这意味着在显示第一个列表后,我按下该;键,并得到相同的绑定。在这种情况下我不需要按;...

weave([1,2,3], [a,b,c], Res).                             
Res = [1, a, 2, b, 3, c] ;
Res = [1, a, 2, b, 3, c].
Run Code Online (Sandbox Code Playgroud)

任何人都能够解释这里发生了什么。谢谢

[*] 不确定这样的谓词是否已经存在,但即使存在,我的目的是学习该语言,因此编写我自己的内置谓词版本非常有用,即使我只使用过内置谓词(并且可能更强大和高效)。

bre*_*ebs 5

这是一个很好的方法:

weave([], _, []).
weave([H|T], L, W) :-
    weave_l_(L, T, H, W).

weave_l_([], _T, _H, []).
weave_l_([LH|LT], T, H, [H, LH|W]) :-
    weave(T, LT, W).
Run Code Online (Sandbox Code Playgroud)

这是使用第一个参数索引来避免不需要的选择点,即[]vs [Head|Tail]

swi-prolog 中的结果:

?- weave([1], [a], W).
W = [1, a].

?- weave([1,2], [a,b], W).
W = [1, a, 2, b].

?- weave([1,2], [a,b,c,d], W).
W = [1, a, 2, b].

?- weave([1,2,3], [a,b,c], W). 
W = [1, a, 2, b, 3, c].
Run Code Online (Sandbox Code Playgroud)

当处于不需要的选择点时,按星号(即 Shift+8)让 swi-prolog 显示解释。