2

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.

false
  • 10,264
  • 13
  • 101
  • 209
HappyHippo
  • 152
  • 3
  • 11
  • Is it that you need something from [Finding all Solutions to a Goal](http://www.swi-prolog.org/pldoc/man?section=allsolutions) – Guy Coder Apr 10 '19 at 11:29
  • I did try findall/3 but I never got it to work quite the way that I needed it to. I have a knowledgebase with two different types of facts. And I need to add all the facts of one type, to a list, if it matches a certain value from the other set of facts. I am not sure if that makes sense though. – HappyHippo Apr 10 '19 at 11:33

1 Answers1

2

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.

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
  • Thank you so much! This actually worked. Do you know a way to make this into one predicate? I have been trying to do that for a while now. I know that is probably not the most optimal way but it would be of great help. Thanks a lot either way though. – HappyHippo Apr 11 '19 at 12:29
  • Yes that makes sense. I'll write up a new one. – HappyHippo Apr 11 '19 at 12:50