0

I have these two lists =

fruits([banana, apple, mangoes, pears]).
foodILike([hamburgers, banana, shakes, fries]).

I want to write a prolog predicate that will return true as soon as it sees 1 items in the foodsILike list in the fruits list. How can I go about doing so?

Jeremiah Willcock
  • 30,161
  • 7
  • 76
  • 78
Waffles
  • 1
  • 2

2 Answers2

3

First, for the plain answer:

fruitsILike(F) :-
  fruits(Fs)
  member(F, Fs),
  foodILike(Ls),
  member(F, Ls).

You could avoid the membership check by flattening the fruits and foods lists:

fruit(banana).
fruit(apple).
...
foodILike(hamburger).
foodILike(banana).
...
fruitsILike(F) :-
  fruit(F),
  foodILike(F).

That said, you seem to try and solve problems in Prolog using imperative idioms, and that won't work. First, predicates do not return anything. When calling a predicate, Prolog unifies its arguments with valid values according to the facts and rules in the program. Therefore, the "returned value" are the assignments to unbound variables. Second, Prolog does not do something "as soon as". It iterates over all possible solutions. You get the first solution, then the second solution, and so on.

Little Bobby Tables
  • 5,261
  • 2
  • 39
  • 49
  • +1. I suggest two improvements to the first version: 1. put both calls to `member` at the end, so Prolog won't need to backtrack over the call to `foodILike`, and 2. use a `memberchk` instead of the second call to `member`. – Fred Foo Feb 27 '11 at 14:17
  • @larsmans: I agree with your improvements, but the second version is the better one anyway. IHMO it is bad practice to put lists in facts; using multi-clause predicates is more natural. – Little Bobby Tables Feb 27 '11 at 20:12
  • @Bobby: true, but the OP's original question was about the intersection of two lists. – Fred Foo Feb 27 '11 at 20:14
1

member can 1) individually generate all the members of a given list and/or 2) give a yes/no answer as to whether a particular element is in a particular list. I believe you want to use the first form on fruits to generate each of the elements of fruit, and the second form on foodILike to see if any of those is present.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • This is news to me - how can I tell if member gives me a yes or no answer? Something like if(member) then (do something). Or is the whole if-statement thing not allowed in prolog? – Waffles Feb 27 '11 at 05:16
  • Hmm...it's been a long time since I wrote any Prolog, so bear with me. You don't (normally anyway) write something like an if-statement -- you just have a rule that will only succeed if some element of X is also an element of Y. You can get a yes/no (or, equivalently, true/false) answer if you enter the same query at the Prolog command prompt, so something like `? member(A, [A, B, C])` will give 'yes' but `? member(A, [B, C])` will give 'no'. In a larger expression, it'll just fail to unify, so the expression as a whole fails. – Jerry Coffin Feb 27 '11 at 05:31
  • @Waffles: you can do if-then-else with (assuming Little Bobby Tables' answer) `fruitsILike(F) -> write(F) ; write('I do not like fruit').` http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html#sec.l10.if.then.else – Fred Foo Feb 27 '11 at 14:25