Prolog:为什么我最终会出现带有匿名变量的列表

时间:2018-10-01 20:46:45

标签: prolog

我只想写一个谓词,它包含两个列表:L1L2,并且我希望第三个元素返回{{1}的前一个N元素},其中L2N的长度。假设我可以假设L1L2长,并且我不想使用内置的L1,所以我尝试这样做:

length

当我尝试时,它给了我

getFirstPart([],_,_).
getFirstPart([H1|T1],[H2|T2],[H2|T3]) :- getFirstPart(T1,T2,T3).

谁能告诉我出什么问题了?谢谢!

2 个答案:

答案 0 :(得分:4)

让我们看一下衍生树。我们从目标开始

getFirstPart([1,1,1],[1,2,3,4,5,6],L).

应用递归规则,我们获得了一个新的目标

getFirstPart([1,1],[2,3,4,5,6],L2).

L = [1 | L2]。在下一个递归步骤中会发生相同的情况:

getFirstPart([1],[3,4,5,6],L3).

L2 = [2 | L2]。再一次,我们获得

getFirstPart([],[4,5,6],L4).

L3 = [3 | L4]。然后,开始执行基本情况。将子替换项放在一起时,得到L = [1,2,3 | L4],对L4无约束。名称_5081628只是Prolog解释器中L4的内部名称。

答案 1 :(得分:2)

自由变量归因于基本情况:

getFirstPart([],_,_).

您基本上在这里写:

  

如果第一个参数为空列表,则我不在乎第二个参数,也不关心第三个参数,它们可以是任何东西。

由于递归案例每次“吃掉”一个元素,最终我们将调用基本案例,因此我们永远不会适当地“关闭”列表。

解决方案是指定最后一个参数的外观:一个空列表,因此:

getFirstPart([],_,[]).
getFirstPart([H1|T1],[H2|T2],[H2|T3]) :-
    getFirstPart(T1,T2,T3).

所以我们在这里或多或少地说:

  

如果第一个参数是空列表,那么我们不在乎第二个参数,但是第三个参数也是空列表。

请注意,在递归情况下,只有一个变量出现一次:H1,我们可以将其替换为下划线_

getFirstPart([],_,[]).
getFirstPart([_|T1],[H2|T2],[H2|T3]) :-
    getFirstPart(T1,T2,T3).