在堆栈溢出的Prolog部分中,谓词 if_/3
似乎是fairly popular。
该谓词是由@false提供的:
if_(If_1, Then_0, Else_0) :-
call(If_1, T),
( T == true -> call(Then_0)
; T == false -> call(Else_0)
; nonvar(T) -> throw(error(type_error(boolean,T),_))
; /* var(T) */ throw(error(instantiation_error,_))
).
但是,我无法找到一个清晰,简单,简洁的解释来说明此谓词的功能以及与例如Prolog
if -> then ; else
的经典if-then-else构造。我发现的大多数链接都直接使用此谓词,而对其使用原因的解释却很少,Prolog的非专家可以轻松理解。
最佳答案
在老式的Prolog代码中,以下模式经常出现:
谓词([],...)。
谓词([L | Ls],...):-
条件(L)
然后(Ls,...)。
谓词([L | Ls],...):-
\ +条件(L),
else(Ls,...)。
我在这里使用列表作为发生这种情况的示例(例如参见include/3
,exclude/3
等),尽管这种模式当然也发生在其他地方。
悲剧如下:
'.'(_, _)
作为主要函子和第一个参数的统一性。 总而言之,现有的构造和语言功能都无法以某种方式表达实践中经常出现的模式。因此,几十年来,似乎有必要妥协。您可以对Prolog社区中的“妥协”通常朝哪个方向做出很好的猜测:几乎总是会在准确性方面牺牲正确性,以免产生疑问。毕竟,只要您的程序运行速度快,谁会关心正确的结果,对吗?因此,在发明
if_/3
之前,这经常被错误地写为:谓词([],...)。
谓词([L | Ls],...):-
(条件(L)->
然后(Ls,...)。
; else(Ls,...)。
)
此处的错误当然是,当元素没有被充分实例化时,即使这两种选择在逻辑上都是可行的,这也可能会错误地提交给一个分支。因此,使用if-then-else几乎总是声明错误,并且由于违反了我们希望从纯Prolog程序获得的最基本属性,因此在声明性调试方法中占据了很大的比例。
使用
if_/3
,您可以这样编写:谓词([],...)。
谓词([L | Ls],...):-
if_(condition(L),
然后(Ls,...),
else(Ls,...))。
和保留所有期望的方面。这是:
的价格相当实惠:正如鲍里斯在评论中提到的那样,您需要实现化。我现在对此有一些经验,并且发现通过一些实践很容易。
大家好消息:在许多情况下,
condition
的形式为(=)/2
或(#=)/2
,并且第一个甚至附带 library(reif)
以获得免费的。有关更多信息,请参阅Ulrich Neumerkel和Stefan Kral的Indexing dif/2!
关于if-statement - if_/3有什么用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39833370/