'if' in prolog?

前端 未结 10 1411
小鲜肉
小鲜肉 2020-12-03 02:12

Is there a way to do an if in prolog, e.g. if a variable is 0, then to do some actions (write text to the terminal). An else isn\'t even needed, but I can\'t find any docume

相关标签:
10条回答
  • 2020-12-03 02:50

    Prolog program actually is big condition for "if" with "then" which prints "Goal is reached" and "else" which prints "No sloutions was found". A, Bmeans "A is true and B is true", most of prolog systems will not try to satisfy "B" if "A" is not reachable (i.e. X=3, write('X is 3'),nl will print 'X is 3' when X=3, and will do nothing if X=2).

    0 讨论(0)
  • 2020-12-03 02:55

    First, let's recall some classical first order logic:

    "If P then Q else R" is equivalent to "(P and Q) or (non_P and R)".


    How can we express "if-then-else" like that in Prolog?

    Let's take the following concrete example:

    If X is a member of list [1,2] then X equals 2 else X equals 4.

    We can match above pattern ("If P then Q else R") if ...

    • condition P is list_member([1,2],X),
    • negated condition non_P is non_member([1,2],X),
    • consequence Q is X=2, and
    • alternative R is X=4.

    To express list (non-)membership in a pure way, we define:

    list_memberd([E|Es],X) :-
       (  E = X
       ;  dif(E,X),
          list_memberd(Es,X)
       ).
    
    non_member(Es,X) :-
       maplist(dif(X),Es).
    

    Let's check out different ways of expressing "if-then-else" in Prolog!

    1. (P,Q ; non_P,R)

      ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4).
      X = 2 ; X = 4.
      ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
      X = 2 ; false.
      ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2.
      X = 2 ; false.
      ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
      X = 4.
      ?-      (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4.
      X = 4.
      

      Correctness score 5/5. Efficiency score 3/5.

    2. (P -> Q ; R)

      ?-      (list_memberd([1,2],X) -> X=2 ; X=4).
      false.                                                % WRONG
      ?- X=2, (list_memberd([1,2],X) -> X=2 ; X=4), X=2.
      X = 2.
      ?-      (list_memberd([1,2],X) -> X=2 ; X=4), X=2.
      false.                                                % WRONG
      ?- X=4, (list_memberd([1,2],X) -> X=2 ; X=4), X=4.
      X = 4.
      ?-      (list_memberd([1,2],X) -> X=2 ; X=4), X=4.
      false.                                                % WRONG
      

      Correctness score 2/5. Efficiency score 2/5.

    3. (P *-> Q ; R)

      ?-      (list_memberd([1,2],X) *-> X=2 ; X=4).
      X = 2 ; false.                                        % WRONG
      ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
      X = 2 ; false.
      ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=2.
      X = 2 ; false.
      ?- X=4, (list_memberd([1,2],X) *-> X=2 ; X=4), X=4.
      X = 4.
      ?-      (list_memberd([1,2],X) *-> X=2 ; X=4), X=4.
      false.                                                % WRONG
      

      Correctness score 3/5. Efficiency score 1/5.


    (Preliminary) summary:

    1. (P,Q ; non_P,R) is correct, but needs a discrete implementation of non_P.

    2. (P -> Q ; R) loses declarative semantics when instantiation is insufficient.

    3. (P *-> Q ; R) is "less" incomplete than (P -> Q ; R), but still has similar woes.


    Luckily for us, there are alternatives: Enter the logically monotone control construct if_/3!

    We can use if_/3 together with the reified list-membership predicate memberd_t/3 like so:

    ?-      if_(memberd_t(X,[1,2]), X=2, X=4).
    X = 2 ; X = 4.
    ?- X=2, if_(memberd_t(X,[1,2]), X=2, X=4), X=2.
    X = 2.
    ?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=2.
    X = 2 ; false.
    ?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
    X = 4.
    ?-      if_(memberd_t(X,[1,2]), X=2, X=4), X=4.
    X = 4.
    

    Correctness score 5/5. Efficiency score 4/5.

    0 讨论(0)
  • 2020-12-03 02:59

    Prolog predicates 'unify' -

    So, in an imperative langauge I'd write

    function bazoo(integer foo)
    {
       if(foo == 5)
           doSomething();
       else
           doSomeOtherThing();
    }
    

    In Prolog I'd write

    bazoo(5) :-  doSomething.
    bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
    

    which, when you understand both styles, is actually a lot clearer.
    "I'm bazoo for the special case when foo is 5"
    "I'm bazoo for the normal case when foo isn't 5"

    0 讨论(0)
  • 2020-12-03 02:59
    (  A == B ->
         writeln("ok")
    ;
         writeln("nok")
    ),
    

    The else part is required

    0 讨论(0)
  • 2020-12-03 03:01

    A standard prolog predicate will do this.

       isfive(5). 
    

    will evaluate to true if you call it with 5 and fail(return false) if you run it with anything else. For not equal you use \=

    isNotEqual(A,B):- A\=B.
    

    Technically it is does not unify, but it is similar to not equal.

    Learn Prolog Now is a good website for learning prolog.

    Edit: To add another example.

    isEqual(A,A). 
    
    0 讨论(0)
  • 2020-12-03 03:04

    The best thing to do is to use the so-called cuts, which has the symbol !.

    if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.  
    if_then_else(Condition, Action1, Action2) :- Action2.
    

    The above is the basic structure of a condition function.

    To exemplify, here's the max function:

    max(X,Y,X):-X>Y,!.  
    max(X,Y,Y):-Y=<X.
    

    I suggest reading more documentation on cuts, but in general they are like breakpoints. Ex.: In case the first max function returns a true value, the second function is not verified.

    PS: I'm fairly new to Prolog, but this is what I've found out.

    0 讨论(0)
提交回复
热议问题