How to use append/3 to recursively build a list in

2019-07-09 01:53发布

问题:

I need to get some values of facts. That part seems to be working.

fact1(A, _, Val1, _, _),
fact2(_, B, Val2, _, _),
A = B,

But as soon as I try to append these values [(Val1,Val2)] to the List(OutList) by using the append/3 predicate, I only get one possible solution back instead of a list with all of them.

Appending like this: append(OutList, [(Val1,Val2)], OutList) doesn't work either. I feel like I am missing something fundamental here.

This is what my predicate looks like so far.

buildList(OutList):-
    fact1(A, _, Val1, _, _),
    fact2(_, B, Val2, _, _),
    A = B,
    append([], [(Val1,Val2)], OutList).

Can someone point me to some mistakes I have made. I know the problem is probably pretty easy to find but I am just starting out with Prolog/functional programming.

Edit: If I had fact1(a,b,c,d,e). and fact2(f,a,g,h,i), then I'd want my predicate to give me a list of all fact2 3rd place value and fact1 third place values as a tuple, where the a matches up with fact1. I have kind of a hard time explaining it, sorry.

回答1:

You were right to look at using findall/3 and should have stuck with it. Your problem is that you walked away from the right path. Don't worry, Einstein did the same with General Relativity, he latter realized his mistake and went back to the correct path.

The first part is to find the individual items, the second part is to collect them into a list.

Given the following facts

fact1(1, _, a, _, _).
fact1(2, _, c, _, _).
fact1(3, _, d, _, _).
fact1(4, _, f, _, _).

fact2(_, 1, b, _, _).
fact2(_, 2, c, _, _).
fact2(_, 4, e, _, _).

Find the individual items:

find_item((Val1,Val2)):-
    fact1(A, _, Val1, _, _),
    fact2(_, A, Val2, _, _).

Then collect them into a list:

findall(Item,find_item(Item),Items).

Now to make it easier to use put it in a predicate:

test(Items) :-
    findall(Item,find_item(Item),Items).

Example run:

?- test(Items).
Items = [(a, b),  (c, c),  (f, e)].

See follow-on question for simpler answer.