在 c 语言中,我有类似的东西:
if(cond1)
{}
else if(cond2)
{}
else
{}
这在 Prolog 中怎么可能?
( If1 -> Then1
; If2 -> Then2
; ...
; otherwise
).
请注意,if-then-else 仅在您无法通过不同子句中的模式匹配来表达不同条件时才需要。可以通过模式匹配表达的一切都应该通过模式匹配来表达,因为这通常会导致更通用和更高效的代码。
(cond1 ->
consequent1
; cond2 ->
consequent2
;
alternative
)
为了记录,这被称为条件。
->/2 仅在您想强加某种确定性时才需要。它的作用类似于局部切割。但是如果你希望你的代码保持一些非确定性,就没有必要使用 ->/2。
采用以下命令式代码:
boolean listOfBool(Object obj) {
if (obj instanceof ConsCell) {
if (((ConsCell)ob).head() instanceof Boolean) {
return listOfBool(((ConsCell)ob).tail());
} else {
return false;
}
} else if (obj == null) {
return true;
} else {
return false;
}
}
这可以在没有 ->/2 的 Prolog 中编码,如下所示:
% bool(+Bool)
% bool(-Bool)
bool(0).
bool(1).
% list_of_bool(+List)
% list_of_bool(-List)
list_of_bool(L) :-
(L = [X|Y], bool(X), list_of_bool(Y);
L = []).
现在的优点是它可以用于检查布尔值列表并生成布尔值列表:
?- list_of_bool([0,1,0]).
Yes
?- list_of_bool([0,1,2]).
No
?- List=[_,_,_], list_of_bool(List).
List = [0, 0, 0] ;
List = [0, 0, 1] ;
List = [0, 1, 0] ;
List = [0, 1, 1] Etc..
通常,析取 (;)/2 可以分布在多个子句中。如果这与将统一 (=)/2 移动到头部相结合,则可以获得一些速度,因为谓词通常更适合索引。
下面是通过消除 (;)/2 和 (=)/2 来替代 list_of_bool 公式的样子:
% list_of_bool2(+List)
% list_of_bool2(-List)
list_of_bool2([X|Y]) :- bool(X), list_of_bool2(Y).
list_of_bool2([]).
上面的工作方式完全相同(它实际上工作得更好,因为在第一个查询中没有留下选择点,如果没有 (->)/2,(;)/2 通常不会检测到什么):
?- list_of_bool2([0,1,0]).
Yes
?- list_of_bool2([0,1,2]).
No
?- List=[_,_,_], list_of_bool(List).
List = [0, 0, 0] ;
List = [0, 0, 1] ;
List = [0, 1, 0] ;
List = [0, 1, 1] Etc..
这也是 Prolog 的启动方式。只有规则,没有析取(;)/2,没有统一(=)/2。后面的两个已经存在于底层的 Horn 子句中。
假设您有一个没有 (;)/2 且没有 (=)/2 的 Prolog,并且您不需要剪切透明 (;)/2,那么您可以自己定义这些构造如下:
X = X.
(A ; _) :- A.
(_ ; B) :- B.
再见
这并不容易找到,部分原因是(正如@mat 所指出的)Prolog 中有一个惯用的替代方案。您可以在此处找到SWI-Prolog 文档,尽管过于简洁,但它是准确的。我引用一个相关的观点:
请注意 (If -> Then) 充当 (If -> Then ; fail),如果条件失败,则使构造失败。这种不寻常的语义是 ISO 和所有事实上的 Prolog 标准的一部分。
if_then_else(Condition,Then,Else) :- Condition, !, Then.
if_then_else(Condition,Then,Else) :- Else.
例如:
max(X,Y,Max) :- if_then_else(X>Y,Max=X,Max=Y).
?- max(4,7,A).
A = 7
?- max(8,2,A).
A = 8