3

I am trying to write the user input into a list but am running into two problems. Using this code

getInput([Symptom|List]):-
    writeln('Enter Element:'),
    read(Symptom),
    dif(Symptom,stop),
    getInput(List).
getInput([]).

I am able to get symptoms from the user but the output shows the first user input as the Head, and the others as the tail. How do I make the Head "Symptoms" and only ad the user input to the Tail? Secondly, when I change "stop" to "Done" the program no longer stops?

So I was told "Done" doesn't work because it is capitalized. If I want to use a capital word, how would I do that?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
  • `Done` is a variable because it starts with an upper case letter and `stop` is not because it does not start with and upper case letter. – Guy Coder Feb 13 '19 at 18:53
  • @GuyCoder ok thank you. So how would i use dif to stop when "Done" is entered and not "done"? – user10876930 Feb 13 '19 at 19:03
  • What happens if you have a symptom that has the same name as your `EOF`, either "stop" or "Done" or whatever, really? The user will never be able to enter that symptom. – User9213 Feb 13 '19 at 19:37
  • @repeat Corrected. Thanks. – Guy Coder Feb 14 '19 at 10:56

2 Answers2

1

This works

get_symptoms(Symptoms) :-
    write('Enter Symptom: ' ),
    read_string(user, "\n", "\r", _, Response),
    (
        Response == "Stop"
    ->
        Symptoms = []
    ;
        get_symptoms(Symptoms0),
        Symptoms = [Response|Symptoms0]
    ).

Uses
1. ==/2 instead of dif/2.
2. read_string/5 instead of read/1 so that strings can be entered.
3. write/1 instead of writeln/1 so that input is on same line as prompt.
4. ->/2 instead of separate clauses.

You can change the value of the exit word to something other than "Stop", you can even use single characters like "." if you like.

Notice also that this does not require a cut (!).

Example runs:

?- get_symptoms(List).
Enter Symptom: Stop
List = [].

?- get_symptoms(List).
Enter Symptom: A
Enter Symptom: Stop
List = ["A"].

?- get_symptoms(List).
Enter Symptom: a
Enter Symptom: A
Enter Symptom: A line with some spaces
Enter Symptom: Notice that a period is not needed at the end
Enter Symptom: Stop
List = ["a", "A", "A line with some spaces", "Notice that a period is not needed at the end"].

How do I make the Head "Symptoms" and only add the user input to the Tail?

You want to make the user input the head and have the following entries as the tail. The trick for this example is to put the list constructor |/2 after the recursive call, e.g.

    get_symptoms(Symptoms0),           % Recursive call
    Symptoms = [Response|Symptoms0]    % List constructor

Secondly, when I change "stop" to "Done" the program no longer stops?

Since Done starts with a capital letter it is a Prolog variable which is causing the problem. stop starts with a lower case letter and is an atom so works as expected with the compare.

If I want to use a capital word, how would I do that?

You can use read/1 which requires the user to input "" when entering the value, e.g.

?- read(X).
|: "Hello".

X = "Hello".

but read/1 reads a term so requires the user to not only add the double quotes but end with a period. Using read_string/5 allows the user to enter data as they would expect. The input will be read and stored as a string. If the data is then to be converted there are predicates that operate on strings

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
0

Try something like this:

get_input( Rs ) :-
  get_input( [], Rs )
  .

get_input( Ss , Rs ) :-
  writeln('Enter Element:'),
  read( S ),
  dif( S , stop ),
  !,
  get_input( [S|Ss] , Rs )
  .
get_input( Rs, Rs ).
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135