我目前正在尝试学习一些基本的序言.在我学习的过程中,我想远离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)
我走向正确的轨道吗?
如果您真的想尝试理解该语言,我建议使用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中进行过程编程,而没有完全学习语言本身.
TL; DR:不要.
您正在尝试将您熟悉的构造从其他编程语言翻译为Prolog.假设学习Prolog意味着基本上将一个构造映射到Prolog之后.毕竟,如果所有构造都已映射,您将能够将任何程序编码为Prolog.
然而,通过这样做,你完全错过了Prolog的本质.
Prolog由纯粹的单调核心和一些程序装饰组成.如果你想了解Prolog与其他编程语言的区别,那么你应该首先研究它的核心.这意味着,你应该忽略那些其他部分.你只有那么多的注意力,如果你浪费时间去处理所有这些非单调的,甚至是程序性的结构,你很可能会错过它的本质.
那么,为什么一般的if-then-else(由几个答案提出)这样一个有问题的结构?有几个原因:
在一般情况下,它打破了单调性.在纯粹的单调Prolog程序中,添加一个新事实将增加您可以从中获得的真实语句集.因此,在添加事实之前的所有事情都将是真实的.正是这个属性允许人们对程序进行非常有效的推理.但请注意,单调性意味着您无法对您可能想要建模的每种情况进行建模.想一个childless/1如果一个人没有孩子就应该成功的谓词.让我们假设这childless(john).是真的.现在,如果你添加一个关于john成为某个孩子的父母的新事实,那么它将不再childless(john)成立.因此,有些情况本身就需要一些非单调结构.但是有许多情况可以在单调部分建模.坚持那些先.
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)
所以有两种可能性.
您的代码存在语法和语义问题。
谓词以小写开头,逗号代表连词。也就是说,您可以将您的条款解读为
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)