if-statement - if_/3 有什么用?

标签 if-statement prolog logical-purity

谓词 if_/3 似乎是 Stack Overflow Prolog 部分的少数主要贡献者之一。

这个谓词是这样实现的,由@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),
否则(Ls,...)。

我在这里使用列表作为发生这种情况的示例(例如,参见 include/3exclude/3 等),尽管这种模式当然也出现在其他地方。

悲剧如下:

  • 对于 实例化 列表中,模式匹配可以区分第一个子句和其余两个子句,但不能区分第二个子句和最后一个子句,因为它们都有 '.'(_, _)作为他们第一个论点的主要仿函数和数量。
  • 最后两个子句适用的条件显然是。互斥 .
  • 因此,当一切都已知时,我们想要获得一个有效的 确定性 不留下选择点的谓词,理想情况下甚至不创建选择点。
  • 但是,只要不是一切都可以安全确定,我们希望从 中受益。回溯 所有解决方案 ,所以我们不能 promise 任何一个条款。

  • 总之,现有的结构和语言特征在某种程度上都不足以表达实践中经常出现的模式。因此,几十年来,似乎有必要妥协。您可以很好地猜测 Prolog 社区中“妥协”通常会朝哪个方向发展:几乎总是为了效率而牺牲正确性,以防有疑问。毕竟,只要你的程序很快,谁会关心正确的结果,对吧?因此,直到 if_/3 的发明,这经常被错误地写成:

    谓词([],...)。
    谓词([L|Ls], ...) :-
    (条件(L)->
    然后(Ls,...)。
    ;否则(Ls,...)。
    )

    错误这当然是当元素没有充分实例化时,即使两种选择在逻辑上都是可能的,这也可能会错误地提交到一个分支。出于这个原因,使用 if-then-else 几乎总是声明性错误,并且由于它违反了我们对纯 Prolog 程序所期望的最基本属性,因此极大地阻碍了声明性调试方法。

    使用 if_/3 ,你可以这样写:

    谓词([],...)。
    谓词([L|Ls], ...) :-
    if_(条件(L),
    那么(Ls, ...),
    否则(Ls,...))。

    保留所有可取的方面 .这是:
  • 确定性 如果一切都可以安全地决定
  • 高效因为它甚至不会创建选择点
  • 完整因为你永远不会错误地提交到一个特定的分支。

  • 价格 这是相当实惠的:正如鲍里斯在评论中提到的,您需要实现 物化 .我现在对此有了一些经验,并且通过一些练习发现它相当容易。

    大家好消息 : 在很多情况下,condition格式为 (=)/2 , 或 (#=)/2 , 第一个甚至附带 library(reif) 免费 .

    如需更多信息,请参阅 Indexing dif/2乌尔里希·纽默克尔和斯特凡·克拉尔!

    关于if-statement - if_/3 有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39833370/

    相关文章:

    Prolog,关于如何形成更好的子句

    java - 多值测试,如何替换许多else if语句?

    list - 有任何内容([_])和任何内容(_)的列表有什么区别

    recursion - 如何创建删除倒数第二个元素的 Prolog 谓词?

    prolog - 我的 Prolog 程序中出现意外循环

    prolog - 是纯Prolog Turing-complete,如果是,为什么不能实现列表交集?

    IOS如何比较具有不同值和元素数量的两个数组

    java - 简单的猜谜游戏。 "Your first guess is...."

    c - 素数输出错误

    prolog - 纯 Prolog 方案 Quine