How to print all the facts?

174 views Asked by At

I am stuck for this problem...

isAt(keys, room3).
isAt(book, room3).
isAt(keys, room6).
isAt(keys, room4).

currently, room3 have keys and book. I want to print keys and book. I tried this code and apparently prints only one. (just keys)

look :- isIn(Location),
  write('You are in '),
  write(Location),
  nl,
  items_inroom(Location),
  nl.


items_inroom(Location) :-
    isIn(Location),
    isAt(Item, Location),
    write('Available Item(s):'), 
    write(Item),
    nl.

items_inroom(_) :-
    write('Available Item(s): None'),
    nl. 

items_inroom is the code that trying to print all these facts. How can I approach this? any help will be great! Thank you.

3

There are 3 answers

2
dlask On BEST ANSWER

Find all items and display them.

items_inroom(Location) :-
    write('Available Item(s):'),
    findall(Item, isAt(Item, Location), Items),
    show_items(Items).

show_items([]) :-
    write('None'), !.

show_items(Items) :- 
    write(Items).

Actually you can implement the show_items(Items) in any way you want.

0
Yasel On

items_inroom/1 predicate will always print the first occurrence of Item on all facts isAt/2. You need to loop over all the facts isAt/2, use a metapredicate setof/3, bagog/3 or findall/3, I will recomend setof/3 like @Boris did, or build your own bucle (maybe not the best idea, but it's an option):

show_items(Location):- isAt(Item, Location),   % Condition
                     write(Item), nl,          % Process result
                     fail.                     % force backtracking to evaluate condition and find a new result
show_items(_).                                 % return true when all options have been evaluated
0
AudioBubble On

From Chapter 11 in "The Craft of Prolog" by Richard O'Keefe, a bit simplified/refactored to save keystrokes:

print_item_report(Location) :-
    (   setof(Item, isAt(Item, Location), Items)
    ->  format("Items available in ~w:~n", [Location]),
        forall(member(I, Items),
               format("~w~n", [I]))
        % print_item_report_footer
    ;   format("No items in ~w~n", [Location])
    ).

% etc

If you don't have format for whatever reason, you can still use write. If you don't have forall, then this:

forall(Condition, Action)

is defined as

\+ (Condition, \+ Action )

so you can use that instead. See the SWI-Prolog forall/2 documentation for details.