0

I have just completed passing some variables down to another method and matching them to facts. I now want to add some security in the form of an if statement. I am hoping to check to see the variable inputted by the user is valid (this is in the form of a number)

An example of this is shown in the code below, basically a user chooses an option between 1 and 10, if the user inputs an invalid option (ie 11) I want the method to print out "invalid choice" and repeat the method.

My question: How do I implement an if statement into Prolog code, the method before the code shown below would pass in a number

ifStatment(X) :-
   write("Here is your list"),
   nl,nl,

   forall(listOfStuff(X,Text), writeln(Text)),
   read(Y),
false
  • 10,264
  • 13
  • 101
  • 209
VicentVega
  • 191
  • 1
  • 4
  • 11
  • Well basically if you write `foo(X), bar(X)`, `foo(X)` acts as an "if statement", since if `foo(X)` fails, then control will never be passed to `bar(X)`. – Willem Van Onsem Nov 19 '18 at 11:46
  • 1
    I see this is related to your earlier question. While I know the back story and others who keep tabs on the Prolog tag will know the back story, when asking related questions it is nice to link to the related questions to help those trying to help you understand what you are thinking. – Guy Coder Nov 19 '18 at 11:46
  • Related question: [Prolog - Write out facts and reading a users input](https://stackoverflow.com/q/53320491/1243762) – Guy Coder Nov 19 '18 at 11:47
  • @WillemVanOnsem I understand what you mean, however from looking into this topic online I am confused on the syntax of the if statement, hence the problem I am having now. – VicentVega Nov 19 '18 at 11:51
  • Of interest: [If statement in Prolog](https://stackoverflow.com/q/9420073/1243762) – Guy Coder Nov 19 '18 at 13:07
  • Is there a reason for no accept vote? – Guy Coder Nov 27 '18 at 18:40

1 Answers1

2

The title of the question IF Statement in Prolog uses the word if which to most programmers brings up the concept of an if statement. In terms of logic programming the word if brings up the concept of the conditional ->/2 or predicates with guard statements. This answer demonstrates both ways on the same problem with the same result.

Extending from your previous question and the accepted answer.

The first way uses the predicate valid_1(N) to check if the input is valid. This does not use ->/2 but uses a two clause predicate with mutually independent guard statements.

The first clause guard statements are:

(0 < N, N < 11)

Note the use of , which means and in Prolog. This reads

N is greater than 0 AND N is less than 11.

The second clause guard statements are:

(N < 1; N > 10)

Note the use of ; which means or in Prolog. This reads

N is less than 1 OR N is greater than 10.

The second way uses the predicate valid_2(N) to check if the input is valid. This uses ->/2.

The format for using the conditional is

(
        % condition
    ->
        % true
    ;
        % false
)

these can be nested and that is done in this example.

Note: The use of the comments % condition, % true and % false are not required. I added them for clarity.

valid_2(N) :-
   (
           % condition
           0 < N
       ->
           % true
           (
                   % condition
                   N < 11
               ->
                    % true
                    writeln("Valid entry.")
               ;
                    % false
                    writeln("Invalid entry. Please try again.")
           )
       ;
            % false
            writeln("Invalid entry. Please try again.")
   ).

Here is the complete code snippet. To change using either valid_1 or valid_2 just make one or the other a comment using %.

tell_me_your_problem:-
    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),
    %valid_1(N),
    valid_2(N),
    do_something_with(Line),
    fail.

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

valid_1(N) :-
   (0 < N, N < 11),
   writeln("Valid entry.").

valid_1(N) :-
   (N < 1; N > 10),
   writeln("Invalid entry. Please try again.").

valid_2(N) :-
   (
           % condition
           0 < N
       ->
           % true
           (
                   % condition
                   N < 11
               ->
                   % true
                   writeln("Valid entry.")
               ;
                   % false
                   writeln("Invalid entry. Please try again.")
           )
       ;
            % false
            writeln("Invalid entry. Please try again.")
   ).

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').

Here is a sample query.

?- tell_me_your_problem.
1
2
3
4
5
6
7
8
9
10
|: 11
Invalid entry. Please try again.
11
|: 0
Invalid entry. Please try again.
0
|: 5
Valid entry.
5
|: quit
Finished
true .
Guy Coder
  • 24,501
  • 8
  • 71
  • 136
  • Trying to follow along here, am I right in understanding that when you write - "*The first way uses the predicate valid_1(N) to check if the input is valid*" - that is not a builtin Prolog predicate, or any special Prolog syntax, but is a predicate you are building yourself, and that the `(N < 0, N > 11)` syntax is using `()` as grouping parentheses around two separate clauses, and not anything more special than that? And that `valid_1` is your name for it, because it has arity 1? – TessellatingHeckler Nov 20 '18 at 18:54
  • @TessellatingHeckler All of your understanding is correct expect for `valid_1` is named `valid_1` because I also have `valid_2` which is a different predicate. Not a bad guess. When writing the arity `\ ` is used, e.g. `valid_1\1` or `valid_2\1` – Guy Coder Nov 20 '18 at 18:57
  • @TessellatingHeckler You know you can give me an up-vote. :) – Guy Coder Nov 20 '18 at 19:01
  • Thanks, that makes sense. :) – TessellatingHeckler Nov 20 '18 at 19:16
  • @TessellatingHeckler Not like doing [Prolog nested in Python](https://codegolf.stackexchange.com/questions/59480/measuring-rectangles/59603#59603) – Guy Coder Nov 20 '18 at 19:18
  • hah, yes, but that made sense considering only one other person answered the golf at all and it took them two years to do it. It's one thing which gave me any tiny interest in Prolog beyond "ancient outdated language" - how come that pattern of "computing with missing values / define the relations and let it fill in the gaps" is so strongly in Prolog and almost completely absent in mainstream languages? Anyway. – TessellatingHeckler Nov 20 '18 at 20:14
  • @TessellatingHeckler As noted in the answer. Prolog uses syntactic unification and most other languages including most functional use assignment. Mercury is both functional and logical and is a rare exception. Also if you jump in to theorem provers and proof assistants you some times see this but they tend to hide it under the covers. Some languages will have a unification library for use but not built-in. – Guy Coder Nov 20 '18 at 20:22