有没有办法在 prolog 中执行 if,例如,如果变量为 0,则执行一些操作(将文本写入终端)。甚至不需要 else,但我找不到任何有关 if 的文档。
10 回答
是的,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
)。
一个标准的 prolog 谓词将执行此操作。
isfive(5).
如果你用 5 调用它,它将评估为 true,如果你用其他任何东西运行它,它会失败(返回 false)。对于不相等,您使用 \=
isNotEqual(A,B):- A\=B.
从技术上讲,它并不统一,但它类似于不相等。
Learn Prolog Now 是一个学习 prolog 的好网站。
编辑:添加另一个示例。
isEqual(A,A).
Prolog谓词'统一' -
所以,我会用命令式语言写
function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}
在 Prolog 我会写
bazoo(5) :- doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
当您了解这两种风格时,实际上会更加清晰。
“当 foo 为 5 时,我是特殊情况下的巴祖”
“当 foo 不是 5 时,我是正常情况下的巴祖”
首先,让我们回顾一些经典的一阶逻辑:
" If P then Q else R" 等价于 "(P and Q) or (non_P and R)"。
我们如何在 Prolog 中表达“if-then-else”?
让我们看下面的具体例子:
If
X
是 list 的成员[1,2]
thenX
等于2
elseX
等于4
。
我们可以匹配上面的模式 (" If P then Q else R") if ...
- 条件
P
是list_member([1,2],X)
, - 否定条件
non_P
是non_member([1,2],X)
, - 结果
Q
是X=2
,并且 - 替代方案
R
是X=4
.
为了以纯粹的方式表达列表(非)成员,我们定义:
list_memberd([E|Es],X) :- ( E = X ; 差异(E,X), list_memberd(Es,X) )。 非成员(Es,X):- 地图列表(差异(X),Es)。
让我们看看在 Prolog 中表达“if-then-else”的不同方式!
(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。
(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。
(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。
(初步)总结:
(P,Q ; non_P,R)
是正确的,但需要离散实现non_P
.(P -> Q ; R)
当实例化不足时失去声明性语义。(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。
我发现这有助于在规则中使用if语句。
max(X,Y,Z) :-
( X =< Y
-> Z = Y
; Z = X
).
感谢http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html
在 Prolog 中表达 if-then-else 之类的东西基本上有三种不同的方式。比较他们考虑char_class/2
。对于a
和b
类应该是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.
所以最后一个答案仍然被压制。现在library(reif)
输入SICStus、YAP和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 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
)
).
最好的办法是使用所谓的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相当陌生,但这就是我发现的。
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)。
( A == B ->
writeln("ok")
;
writeln("nok")
),
else部分是必需的
您应该立即阅读Learn Prolog!第 10.2 章使用 Cut。这提供了一个示例:
max(X,Y,Z) :- X =< Y,!, Y = Z.
可以说,
Z
等于Y
IF !
为真(它总是如此)AND X
为<= Y
.