'if' in prolog?

前端 未结 10 1483
小鲜肉
小鲜肉 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: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
         )
       ).
    

提交回复
热议问题