You need to allow Prolog to backtrack to get all of the solutions. The problem with your predicate is that it does a recursive call before it can backtrack. Also, you continue to recurse one level deeper for the next menu prompt which is probably not good practice since it continually consumes more stack as it responds to user inputs.
Here's another approach, using the repeat/0
predicate along with fail/0
. repeat/0
simply succeeds which allows to re-query for solutions during backtracking. And fail/0
always fails, which forces backtracking. It's a common way to do a continual repeat loop and works well for looping on a menu. I've also adjusted the nl/0
usage a bit to make the output a little neater, and I renamed time/2
since it is just too generic a name and could potentially collide with a system predicate.
item_time(office_hour,1).
item_time(office_hour,2).
menu1 :-
repeat,
nl, write('Input time'), nl,
read(Y),
item_time(Y, X),
write(X), nl,
fail.
This will yield:
| ?- menu1.
Input time
office_hour.
1
2
Input time
foo.
Input time
...
What happens here is that fail/0
will cause the predicate clause to backtrack through the write(X), nl
and to the time(Y, X)
which will come up with the alternate solutions, succeed on those solutions, and then move forward to the write(X), nl
again. If time(Y, X)
finds no more solutions, then it finally fails and the clause backtracks all the way back to the repeat/0
call, which always succeeds. That results in the execution moving forward again to the nl, write('Input time'), ...
.
As you can see, inputting something unrecognized just re-prompts. To make this more complete, you could add atoms that are recognized as a "quite" and you could write a diagnostic message if you get input that doesn't exist in your database. That would be a good exercise for learning.