没有if和else语句的Prolog

use*_*608 7 logic prolog

我目前正在尝试学习一些基本的序言.在我学习的过程中,我想远离if else语句来真正理解语言.我这样做有困难.我有一个看起来像这样的简单函数:

if a > b then 1
else if
   a == b then c
else
    -1;;
Run Code Online (Sandbox Code Playgroud)

这只是一个非常简单的逻辑,我想转换成prolog.

所以在这里我非常困惑.我想首先检查一个> b,如果是这样输出1.我只是这样做:

sample(A,B,C,O):-
   A > B, 1,
   A < B, -1,
   0.
Run Code Online (Sandbox Code Playgroud)

这就是我提出的.o作为输出,但我不明白如何使输出1.有什么想法可以帮我更好地理解这个吗?

在做了一些之后我想出了这个,但它似乎不正确:

Greaterthan(A,B,1.0).
Lessthan(A,B,-1.0).
Equal(A,B,C).

Sample(A,B,C,What):-
    Greaterthan(A,B,1.0),
    Lessthan(A,B,-1.0),
    Equal(A,B,C).
Run Code Online (Sandbox Code Playgroud)

我走向正确的轨道吗?

SQB*_*SQB 6

如果您真的想尝试理解该语言,我建议使用CapelliC的第一个建议:

sample(A, B, _,  1) :- A > B.
sample(A, B, C,  C) :- A == B.
sample(A, B, _, -1) :- A < B.
Run Code Online (Sandbox Code Playgroud)

我不同意CappeliC你应该使用if/then/else语法,因为这种方式(根据我的经验)很容易陷入翻译不同结构的陷阱,最终在Prolog中进行过程编程,而没有完全学习语言本身.


fal*_*lse 6

TL; DR:不要.

您正在尝试将您熟悉的构造从其他编程语言翻译为Prolog.假设学习Prolog意味着基本上将一个构造映射到Prolog之后.毕竟,如果所有构造都已映射,您将能够将任何程序编码为Prolog.

然而,通过这样做,你完全错过了Prolog的本质.

Prolog由纯粹的单调核心和一些程序装饰组成.如果你想了解Prolog与其他编程语言的区别,那么你应该首先研究它的核心.这意味着,你应该忽略那些其他部分.你只有那么多的注意力,如果你浪费时间去处理所有这些非单调的,甚至是程序性的结构,你很可能会错过它的本质.

那么,为什么一般的if-then-else(由几个答案提出)这样一个有问题的结构?有几个原因:

  1. 在一般情况下,它打破了单调性.在纯粹的单调Prolog程序中,添加一个新事实将增加您可以从中获得的真实语句集.因此,在添加事实之前的所有事情都将是真实的.正是这个属性允许人们对程序进行非常有效的推理.但请注意,单调性意味着您无法对您可能想要建模的每种情况进行建模.想一个childless/1如果一个人没有孩子就应该成功的谓词.让我们假设这childless(john).是真的.现在,如果你添加一个关于john成为某个孩子的父母的新事实,那么它将不再childless(john)成立.因此,有些情况本身就需要一些非单调结构.但是有许多情况可以在单调部分建模.坚持那些先.

  2. if-then-else容易导致难以阅读的嵌套.只要看看你的if-then-else程序,然后尝试回答"结果何时为-1"?答案是:"如果既不a > b是真的也不a == b是真的".很冗长,不是吗?因此,维护,修改和调试程序的人员必须"付费".

从你的例子中不清楚你正在考虑什么参数,如果你对整数感到满意,可以考虑使用library(clpfd)它在SICStus,SWI,YAP中可用:

sample(A,B,_,1) :- A #> B.
sample(A,B,C,C) :- A #= B.
sample(A,B,_,-1) :- A #< B.
Run Code Online (Sandbox Code Playgroud)

这个定义现在很普遍,你甚至可以问

什么时候-1退回?

?- sample(A,B,C,-1).
  A = B,
  C = -1,
  B in inf..sup
;
  A#=<B+ -1.
Run Code Online (Sandbox Code Playgroud)

所以有两种可能性.


Cap*_*liC 2

您的代码存在语法和语义问题。

谓词以小写开头,逗号代表连词。也就是说,您可以将您的条款解读为

sample(A,B,C,What) if
    greaterthan(A,B,1.0) and lessthan(A,B,-1.0) and equal(A,B,C).
Run Code Online (Sandbox Code Playgroud)

然后请注意,该What参数是无用的,因为它没有获得值 - 它被称为单例。

一种可能的写析取(即 OR)的方式

sample(A,B,_,1) :- A > B.
sample(A,B,C,C) :- A == B.
sample(A,B,_,-1) :- A < B.
Run Code Online (Sandbox Code Playgroud)

注意测试A < B以保护值的分配-1。这是必要的,因为 Prolog 将在需要时执行所有子句。强制 Prolog 避免某些我们知道应该执行的计算的基本构造是cut

sample(A,B,_,1) :- A > B, !.
sample(A,B,C,C) :- A == B, !.
sample(A,B,_,-1).
Run Code Online (Sandbox Code Playgroud)

不管怎样,我认为你应该使用 if/then/else 语法,即使在学习时也是如此。

sample(A,B,C,W) :- A > B -> W = 1 ; A == B -> W = C ; W = -1.
Run Code Online (Sandbox Code Playgroud)