if_ / 3有什么用? [英] What use does if_/3 have?

查看:173
本文介绍了if_ / 3有什么用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谓词 if_ / 3 似乎是少数几个主要的相当受欢迎的 Stack Overflow的Prolog部分中的贡献者。

The predicate if_/3 seems to be fairly popular among the few main contributors in the Prolog part of Stack Overflow.

这个谓词是这样实现的,由@false提供:

This predicate is implemented as such, courtesy of @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 - >然后 ;其他

However, I have been unable to find a clear, simple, and concise explanation of what this predicate does, and what use it has compared to e.g. the classical if-then-else construct of Prolog if -> then ; else.

我发现的大多数链接直接使用这个谓词,并且提供了很少的解释,为什么它被使用,Prolog中的非专家可以轻松理解。

Most links I have found directly use this predicate and provide little explanation as to why it gets used, that a non-expert in Prolog could understand easily.

推荐答案

在老式的Prolog代码中,以下模式经常出现:

In old-fashioned Prolog code, the following pattern arises rather frequently:


predicate([], ...).
predicate([L|Ls], ...) :-
        condition(L),
        then(Ls, ...).
predicate([L|Ls], ...) :-
        \+ condition(L),
        else(Ls, ...).

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

I am using lists here as an example where this occurs (see for example include/3, exclude/3 etc.), although the pattern of course also occurs elsewhere.

悲剧如下:


  • 对于实例化列表,模式匹配可以将第一个子句与剩余的两个子句区分开来,但它无法区分第二个和最后一个,因为他们两个都有'。(_,_)作为主要的仿函数和他们的第一个论点。

  • 最后两个条款适用的条件显然是互相排斥

  • 因此当一切都已知时,我们希望获得一个有效的确定性谓词不会留下选择点,理想情况下甚至不会创建选择积分。

  • 然而,只要不是一切都可以安全地确定我们希望受益于回溯以查看所有解决方案,因此我们无法承担任何条款。

  • For an instantiated list, pattern matching can distinguish the first clause from the remaining two, but it cannot distinguish the second one from the last one because they both have '.'(_, _) as the primary functor and arity of their first argument.
  • The conditions in which the last two clauses apply are obviously mutually exclusive.
  • Thus, when everything is known, we want to obtain an efficient, deterministic predicate that does not leave choice points, and ideally does not even create choice points.
  • However, as long as not everything can be safely determined, we want to benefit from backtracking to see all solutions, so we cannot afford to commit to either of the clauses.

总之,现有的结构和语言功能在某种程度上都不足以表达在实践中经常出现的模式。因此,几十年来,似乎有必要妥协。你可以很好地猜测Prolog社区中妥协的方向:几乎无一例外,如果有疑问,正确性会因效率而牺牲。毕竟,只要你的节目很快,谁会关心正确的结果,对吧?因此,在 if_ / 3 的发明之前,这经常是错误地写成:

In summary, the existing constructs and language features all fall short in some way to express a pattern that often occurs in practice. Therefore, for decades, it seemed necessary to compromise. And you can make a pretty good guess in which direction the "compromises" usually go in the Prolog community: Almost invariably, correctness is sacrificed for efficiency in case of doubt. After all, who cares about correct results as long as your programs are fast, right? Therefore, until the invention of if_/3, this was frequently wrongly written as:


predicate([], ...).
predicate([L|Ls], ...) :-
        (    condition(L) ->
             then(Ls, ...).
        ;    else(Ls, ...).
        )

错误 in这当然是当元素充分实例化时,即使两个替代方案在逻辑上是可能的,这可能错误地提交到一个分支。由于这个原因,使用if-then-else几乎总是声明性错误,并且由于它违反了我们对纯Prolog程序所期望的最基本属性而大量采用声明式调试方法。

The mistake in this is of course that when the elements are not sufficiently instantiated, then this may incorrectly commit to one branch even though both alternatives are logically possible. For this reason, using if-then-else is almost always declaratively wrong, and stands massively in the way of declarative debugging approaches due to its violation of the most elementary properties we expect from pure Prolog programs.

使用 if_ / 3 ,您可以将其写成:

Using if_/3, you can write this as:


predicate([], ...).
predicate([L|Ls], ...) :-
        if_(condition(L),
            then(Ls, ...),
            else(Ls, ...)).

保留所有理想的方面。这是:


  • 确定性如果一切都可以安全地决定

  • 高效,因为它甚至没有创建选择点

  • 完成,因为你永远不会

  • deterministic if everything can be safely decided
  • efficient in that it does not even create choice points
  • complete in that you never incorrectly commit to one particular branch.

价格的价格相当实惠:鲍里斯在评论中提到,你需要实施具体化。我现在对此有一些经验,并且通过一些练习发现它相当容易。

The price of this is rather affordable: As Boris mentioned in the comments, you need to implement a reification. I have now some experience with this and found it rather easy with some practice.

每个人都好消息:在很多情况下,条件的格式为(=)/ 2 ,或(#=)/ 2 ,第一批甚至还附带 图书馆(reif) 免费

Good news everyone: In many cases, condition is of the form (=)/2, or (#=)/2, and the first even ships with library(reif) for free.

有关更多信息,请参阅Ulrich Neumerkel和Stefan的 Indexing dif / 2 。克拉尔!

For more information, see Indexing dif/2 by Ulrich Neumerkel and Stefan Kral!

这篇关于if_ / 3有什么用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆