'如果'在序言中?

发布于 2024-09-01 11:25:58 字数 79 浏览 1 评论 0原文

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

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 documentation of if.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

浸婚纱 2024-09-08 11:25:58

是的,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)。

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

呆头 2024-09-08 11:25:58

标准的序言谓词将执行此操作。

   isfive(5). 

如果您使用 5 调用它,则评估结果为 true;如果您使用其他任何值运行它,则评估结果为失败(返回 false)。对于不等于,您使用 \=

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

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

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

编辑:
添加另一个例子。

isEqual(A,A). 

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). 
脱离于你 2024-09-08 11:25:58

Prolog 谓词“统一” -

因此,在命令式语言中,我会写

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

在 Prolog 中,当您理解两种风格时,我会写

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

,实际上会更清晰。
“我对 foo 为 5 时的特殊情况感到非常满意”
“当 foo 不是 5 时,我对正常情况很满意”

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"

七秒鱼° 2024-09-08 11:25:58

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

如果 P Q else R”相当于“(P Q) (非_P R)”。


我们怎样才能像 Prolog 中的 that 一样表达“if-then-else”?

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

如果 X 是列表[1,2] 的成员 X 等于 2 else X 等于 4


我们可以匹配上面的模式(“If P then Q else R”)如果...

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

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

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

non_member(Es,X) :-
   maplist(dif(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) 的不完整程度“更少”,但仍然有类似的问题。< /p>


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

我们可以使用if_/3 与具体化列表成员谓词 memberd_t/3< /a> 像这样:

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

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

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.

尝蛊 2024-09-08 11:25:58

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

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

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

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

时光是把杀猪刀 2024-09-08 11:25:58

在 Prolog 中表达 if-then-else 之类的内容本质上有三种不同的方式。要比较它们,请考虑 char_class/2。对于 ab ,类应为 ab ,对于所有其他术语,类应为 other 。人们可能会像这样笨拙地写这个:

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.

所以最后一个答案仍然被抑制。现在输入 Scryer 的 library(reif)SICStusYAP< /a> 和 SWI。安装它并说:

?- 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,其

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

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 Scryer, 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
      )
   ).
瞳孔里扚悲伤 2024-09-08 11:25:58

最好的办法是使用所谓的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 相当陌生,但这就是我发现的。

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.

傾城如夢未必闌珊 2024-09-08 11:25:58

Prolog 程序实际上是“if”的大条件,“then”打印“目标已达到”,“else”打印“未找到解决方案”。 A, B表示“A为真且B为真”,如果“A”不可到达,大多数prolog系统不会尝试满足“B”(即X=3,写('X is 3'),nl 当 X=3 时将打印 'X is 3',如果 X=2 将不执行任何操作)。

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

会发光的星星闪亮亮i 2024-09-08 11:25:58
(  A == B ->
     writeln("ok")
;
     writeln("nok")
),

else 部分为必填项

(  A == B ->
     writeln("ok")
;
     writeln("nok")
),

The else part is required

做个ˇ局外人 2024-09-08 11:25:58

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

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

可以说,

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文