'if' in prolog?

前端 未结 10 1414
小鲜肉
小鲜肉 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 03:06

    I found this helpful for using an if statement in a rule.

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

    Thanks to http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html

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

    Yes, there is such a control construct in ISO Prolog, called ->. You use it like this:

    ( condition -> then_clause ; else_clause )
    

    Here is an example that uses a chain of else-if-clauses:

    (   X < 0 ->
        writeln('X is negative.  That's weird!  Failing now.'),
        fail
    ;   X =:= 0 ->
        writeln('X is zero.')
    ;   writeln('X is positive.')
    )
    

    Note that if you omit the else-clause, the condition failing will mean that the whole if-statement will fail. Therefore, I recommend always including the else-clause (even if it is just true).

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

    You should read Learn Prolog Now! Chapter 10.2 Using Cut. This provides an example:

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

    to be said,

    Z is equal to Y IF ! is true (which it always is) AND X is <= Y.

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

    There are essentially three different ways how to express something like if-then-else in Prolog. To compare them consider char_class/2. For a and b the class should be ab and other for all other terms. One could write this clumsily like so:

    char_class(a, ab).
    char_class(b, ab).
    char_class(X, other) :-
       dif(X, a),
       dif(X, b).
    
    ?- char_class(Ch, Class).
       Ch = a, Class = ab
    ;  Ch = b, Class = ab
    ;  Class = other,
       dif(Ch, a), dif(Ch, b).
    

    To write things more compactly, an if-then-else construct is needed. Prolog has a built-in one:

    ?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
       Ch = a, Class = ab.
    

    While this answer is sound, it is incomplete. Just the first answer from ( Ch = a ; Ch = b ) is given. The other answers are chopped away. Not very relational, indeed.

    A better construct, often called a "soft cut" (don't believe the name, a cut is a cut is a cut), gives slightly better results (this is in YAP):

    ?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
       Ch = a, Class = ab
    ;  Ch = b, Class = ab.
    

    Alternatively, SICStus has if/3 with very similar semantics:

    ?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
       Ch = a, Class = ab
    ;  Ch = b, Class = ab.
    

    So the last answer is still suppressed. Now enter library(reif) for SICStus, YAP, and SWI. Install it and say:

    ?- use_module(library(reif)).
    
    ?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
       Ch = a, Class = ab
    ;  Ch = b, Class = ab
    ;  Class = other,
       dif(Ch, a), dif(Ch, b).
    

    Note that all the if_/3 is compiled away to a wildly nested if-then-else for

    char_class(Ch, Class) :-
       if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
    

    which expands in YAP 6.3.4 to:

    char_class(A,B) :-
       ( A\=a
       ->
         ( A\=b
         ->
           B=other
         ;
           ( A==b
           ->
             B=ab
           )
         ;
           A=b,
           B=ab
         ;
           dif(A,b),
           B=other
         )
       ;
         ( A==a
         ->
           B=ab
         )
       ;
         A=a,
         B=ab
       ;
         dif(A,a),
         ( A\=b
         ->
           B=other
         ;
           ( A==b
           ->
             B=ab
           )
         ;
           A=b,
           B=ab
         ;
           dif(A,b),
           B=other
         )
       ).
    
    0 讨论(0)
提交回复
热议问题