Prolog - Write out facts and reading a users input

2019-01-28 12:30发布

问题:

I am quite new to Prolog and have had some trouble understanding it. I have some facts named 'problem' I wish to first print out these facts to the user and then ask them to input a value, this value is then read and used later.

From my understanding thus far, it would be best to use a forall to print out these facts and then use read to read the value inputted, but I am having some issue implementing this. Here is what I have so far, any explanation would be appreciated

My question: How do I read in the input from the user regarding the problem and apply that into a variable for later use?

tellMeYourProblem:-
forall(problem(P), 
writeln(P)),
answer = read(X),


problem('1').
problem('2').
problem('3').
problem('4').
problem('5').
problem('6').
problem('7').
problem('8').
problem('9').
problem('10').

回答1:

Note: This answer uses SWI-Prolog.

How do I read in the input from the user regarding the problem?

You are doing that already with read(X), however read/1 reads terms (terms end with periods) and you probably want to read characters. If you are using SWI-Prolog take a look at Primitive character I/O for reading characters and Predicates that operate on strings for reading strings.

How do I apply that into a variable for later use?

When doing basic I/O with a user at a text level, a REPL is a good way to start. Adding a REPL is a bit more complicated so I will give you the code.

tellMeYourProblem:-
    output_problems,
    read_input.

output_problems :-
    forall(problem(P),
    writeln(P)).

read_input :-
    repeat,
    read_string(user_input, "\n", "\r\t ", _, Line),
    process_input(Line).

process_input(Line) :-
    string(Line),
    atom_number(Line, N),
    integer(N),
    do_something_with(Line),
    fail.

process_input("quit") :-
    write('Finished'), nl,
    !, true.

do_something_with(X) :-
    writeln(X).


problem('1').
problem('2').
problem('3').
problem('4').
problem('5').
problem('6').
problem('7').
problem('8').
problem('9').
problem('10').

Also with Prolog, the style is to use snake casing so tellMeYourProblem should be changed.

Normally in Prolog a REPL is done with ->/2, (Read Input till quit statement Prolog) , but I changed this to add more guard statements so that the exit condition would work, e.g.

string(Line),
atom_number(Line, N),
integer(N)

or putting the guard in the head, e.g.

process_input("quit")

When doing I/O to a screen and keyboard, the thought is to use stdIn and stdOut but for the keyboard SWI-Prolog uses user_input instead. See: Input and output

After all of the boiler plate code for the REPL is the next part you seek which is to do something with the input value, in this case just print it out.

do_something_with(X) :-
    writeln(X).


回答2:

The easiest to write out the facts of problem/1, is to use the builtin listing/[0,1]. This builtin accepts a so called predicate indicator. You can write out the facts via:

?- listing(problem/1).

The predicate is supported by many Prolog systems such as GNU Prolog, etc.. For how to read input see for example the post by Guy Coder.