Reputation: 103
I would just like to write a predicate, which takes two lists: L1
and L2
, and I want the third element to return the first N
elements of L2
, where N
is the length of L1
. Suppose I could assume that L2
is longer than L1
, and I do not want to use the built-in length
, so I tried to do like this:
getFirstPart([],_,_).
getFirstPart([H1|T1],[H2|T2],[H2|T3]) :- getFirstPart(T1,T2,T3).
And when I try, it gives me
?- getFirstPart([1,1,1],[1,2,3,4,5,6],L).
L = [1, 2, 3|_5081628].
Could anyone tell me what is wrong? Thanks!
Upvotes: 4
Views: 950
Reputation: 4998
Let's have a look at the derivation tree. We start with the goal
getFirstPart([1,1,1],[1,2,3,4,5,6],L).
Applying the recursive rule, we obtain a new goal
getFirstPart([1,1],[2,3,4,5,6],L2).
with L = [1 | L2]
. The same happens during the next recursion step:
getFirstPart([1],[3,4,5,6],L3).
with L2 = [2 | L2]
. Once more and we obtain
getFirstPart([],[4,5,6],L4).
with L3 = [3 | L4]
. Then the base case kicks in. When we put the substiutions together we obtain L = [1,2,3 | L4]
with no constraints on L4
. The name _5081628
is just the internal name of L4
in your Prolog interpreter.
Upvotes: 4
Reputation: 476813
The free variable is due to the base-case:
getFirstPart([],_,_).
Here you write basically:
If the first parameter is the empty list, I do not care about the second parameter, nor the third, these can be anything.
Since the recursive case each time "eats" an element, eventually we will invoke the base case, and so we never properly "close" the list.
The solution is to specify how the last parameter should look like: an empty list, so:
getFirstPart([],_,[]).
getFirstPart([H1|T1],[H2|T2],[H2|T3]) :-
getFirstPart(T1,T2,T3).
So here we more or less say:
If the first parameter is the empty list, then we do not care about the second parameter, but the third parameter is the empty list as well.
Note that in the recursive case, there is an variable that only occurs once: H1
, we can replace this with an underscore _
:
getFirstPart([],_,[]).
getFirstPart([_|T1],[H2|T2],[H2|T3]) :-
getFirstPart(T1,T2,T3).
Upvotes: 2