理解Prolog中的列表和递归

时间:2012-05-10 17:32:54

标签: prolog

我在Prolog中思考困难。这句话的错误是什么:

numberList([], 0).
numberList([H|T], Limit) :-
    H is Limit,
    numberList(T, Limit - 1).

我想

?- numberList(X,Limit).

[Limit, Limit-1 ... 1]确定为Limit的给定值的唯一解,即

?- numberList(X, 100).

会产生X = [100, 99, 98, ..., 1].

我的猜测是,我的理解存在一些非常错误,因为这不能起作用。我不一定要求解决我想要做的事情,我只想理解为什么我的第一次尝试是错误的。

2 个答案:

答案 0 :(得分:3)

潜伏在这里有两个主要问题:

1-您在正确的地方获得统一和算术运算很麻烦

2-你没有检查你的输入

关于1- (is)/2的备注用于执行算术,例如,它将1减去Limit(is)/2可以但不应该用于将变量统一到已经评估的算术表达式。 (=)/2应该优先考虑(统一)。

关于2-的备注,即使你使运算符正确,你的程序也会循环。稍后会详细介绍。

只需自己切换操作员就不会获得太多收益,所以这是正确的方法:

numberList([], 0).
numberList([Limit|T], Limit) :-
    NewLimit is Limit - 1,
    numberList(T, NewLimit).

在这里你可以看到我在第二个条款的头部隐含地使用统一,另一种方式是将它放在下面:

numberList([], 0).
numberList([H|T], Limit) :-
    H = Limit,
    NewLimit is Limit - 1,
    numberList(T, NewLimit).

但现在,正如您通过尝试此程序所看到的那样,它会找到一个正确的解决方案,但如果您要求另一个;,则会循环。

原因可能更难以发现初学者的眼睛:当Prolog成功并返回解决方案时,它只能通过探索执行期间留下的选择点来找到新的解决方案。在此,唯一的选择点是Limit0时。因此它会尝试第二个子句而不是第一个子句,然后循环直到达到NegativeInfinity。可悲的是,由于到达那里的行程很长,所以之前会溢出。这个问题的解决方案是为第二个子句添加一个保护,指定Limit应该大于0或者为第一个子句添加一个切口甚至更好:两者都做。问你自己是否有麻烦!

答案 1 :(得分:0)

"限制 - 1"正在被认为是一个函数调用,用C语言,它可以工作。它要求/命令Prolog"找到一个减法函数,用Limit-variable和1"来调用它。它要求Prolog理解"限制 - 1"作为函数调用结果,但Prolog理解"限制 - 1"作为复合项减法(Limit,1),它是来自一阶逻辑的谓词

" H是限制"这也被认为是函数调用

Prolog没有功能(???),我认为这个说法对C人来说是一个很大的障碍。而不是函数(与C等一样,与数学一样),Prolog有谓词(如谓词逻辑,一阶等)

Function是命令微处理器的命令。相反,谓词将数据呈现给微处理器,以便用微处理器的眼睛看,将数据呈现给微处理器以进行感知。

谓词描述一个世界,描述该世界中对象之间的某些关系,微处理器试图验证这些关系。微处理器试图证明这些关系确实存在于它的知识中。这些关系可以在其知识中多次存在,因此微处理器可以返回多个结果(又称非确定性)

Prolog是一种很棒的编程语言,可能我应该写出精彩的描述语言,梦幻般的模式识别语言,梦幻般的推理/演绎语言(简单的推理/演绎,它不是一种"人工智能",数字电子逻辑门中的推论/推论)。我以前是一个渴望的Visual Studio程序员,但我已经研究了Prolog几年了。

C语言等用于命令,Prolog语言等用于描述。