73

有没有办法在 prolog 中执行 if,例如,如果变量为 0,则执行一些操作(将文本写入终端)。甚至不需要 else,但我找不到任何有关 if 的文档。

4

10 回答 10

107

是的,ISO Prolog 中有这样一个控制结构,称为->. 你像这样使用它:

( condition -> then_clause ; else_clause )

这是一个使用 else-if 子句链的示例:

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

请注意,如果您省略 else 子句,则条件失败将意味着整个 if 语句将失败。因此,我建议始终包含 else 子句(即使它只是true)。

于 2011-06-11T08:25:59.807 回答
54

一个标准的 prolog 谓词将执行此操作。

   isfive(5). 

如果你用 5 调用它,它将评估为 true,如果你用其他任何东西运行它,它会失败(返回 false)。对于不相等,您使用 \=

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

从技术上讲,它并不统一,但它类似于不相等。

Learn Prolog Now 是一个学习 prolog 的好网站。

编辑:添加另一个示例。

isEqual(A,A). 
于 2010-05-17T14:13:44.237 回答
31

Prolog谓词'统一' -

所以,我会用命令式语言写

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

在 Prolog 我会写

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

当您了解这两种风格时,实际上会更加清晰。
“当 foo 为 5 时,我是特殊情况下的巴祖”
“当 foo 不是 5 时,我是正常情况下的巴祖”

于 2011-12-09T22:13:40.737 回答
16

首先,让我们回顾一些经典的一阶逻辑:

" If P then Q else R" 等价于 "(P and Q) or (non_P and R)"。


我们如何在 Prolog 中表达“if-then-else”?

让我们看下面的具体例子:

If X是 list 的成员[1,2] then X等于2 else X等于4

我们可以匹配上面的模式 (" If P then Q else R") if ...

  • 条件Plist_member([1,2],X)
  • 否定条件non_Pnon_member([1,2],X),
  • 结果QX=2,并且
  • 替代方案RX=4.

为了以纯粹的方式表达列表(非)成员,我们定义:

list_memberd([E|Es],X) :-
   ( E = X
   ; 差异(E,X),
      list_memberd(Es,X)
   )。

非成员(Es,X):-
   地图列表(差异(X),Es)。

让我们看看在 Prolog 中表达“if-then-else”的不同方式!

  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 ; 假的。
    ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2。
    X = 2 ; 假的。
    ?- 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。
    

    正确性得分 5/5。效率得分 3/5。

  2. (P -> Q ; R)

    ?- (list_memberd([1,2],X) -> X=2 ; X=4)。
    的。% 错误的
    ?- 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。
    的。% 错误的
    ?- 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。
    的。% 错误的
    

    正确性得分 2/5。效率得分 2/5。

  3. (P *-> Q ; R)

    ?- (list_memberd([1,2],X) *-> X=2 ; X=4)。
    X = 2 ; 假的。% 错误的
    ?- 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。
    X = 2 ; 假的。
    ?- 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。
    的。% 错误的
    

    正确性得分 3/5。效率得分 1/5。


(初步)总结:

  1. (P,Q ; non_P,R)是正确的,但需要离散实现non_P.

  2. (P -> Q ; R)当实例化不足时失去声明性语义。

  3. (P *-> Q ; R)比 不完整(P -> Q ; R),但仍然有类似的问题。


对我们来说幸运的是,还有其他选择: 输入逻辑上单调的控制结构if_/3

我们可以像这样if_/3与 reified list-membership 谓词一起使用memberd_t/3

?- 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 ; 假的。
?- 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。

正确性得分 5/5。效率得分 4/5。

于 2015-10-16T15:08:20.913 回答
15

我发现这有助于在规则中使用if语句。

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

感谢http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html

于 2012-12-07T00:20:03.370 回答
9

在 Prolog 中表达 if-then-else 之类的东西基本上有三种不同的方式。比较他们考虑char_class/2。对于ab类应该是abother对于所有其他术语。可以这样笨拙地写:

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

为了写得更紧凑,需要一个 if-then-else 结构。Prolog 有一个内置的:

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

虽然这个答案是合理的,但它是不完整的。只是给出了第一个答案( Ch = a ; Ch = b )。其他答案被砍掉了。确实,关系不大。

一个更好的结构,通常称为“软切割”(不要相信这个名字,一个切割就是一个切割),会产生更好的结果(这是在 YAP 中):

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

或者,SICStus 具有if/3非常相似的语义:

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

所以最后一个答案仍然被压制。现在library(reif)输入SICStusYAPSWI。安装它并说:

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

请注意,所有的if_/3都被编译成一个疯狂嵌套的 if-then-else for

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

在 YAP 6.3.4 中扩展为:

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
     )
   ).
于 2016-05-05T18:27:49.283 回答
4

最好的办法是使用所谓的cuts,其中有符号!

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

以上是条件函数的基本结构。

举例来说,这里的max功能:

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

我建议阅读更多关于削减的文档,但总的来说它们就像断点。例如:如果第一个max函数返回真值,则第二个函数不会被验证。

PS:我对Prolog相当陌生,但这就是我发现的。

于 2013-10-11T07:52:19.733 回答
3

Prolog程序实际上是“if”的大条件,“then”打印“Goal is达到”和“else”打印“No sloutions were found”。A, B表示“A 为真,B 为真”,如果“A”不可达,大多数 prolog 系统将不会尝试满足“B”(即X=3, write('X is 3'),nl当 X=3 时将打印 'X is 3',如果 X 则不执行任何操作=2)。

于 2010-05-17T13:57:12.203 回答
3
(  A == B ->
     writeln("ok")
;
     writeln("nok")
),

else部分是必需的

于 2014-07-07T21:53:26.737 回答
1

您应该立即阅读Learn Prolog!第 10.2 章使用 Cut。这提供了一个示例:

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

可以说,

Z等于Y IF !为真(它总是如此)AND X<= Y.

于 2016-12-05T19:38:48.913 回答