between/3可以不递归吗?

Can between/3 not be recursive?

我看过 Prolog Prologue between/3 的定义:

between(Lower, Upper, Lower) :-
   Lower =< Upper.
between(Lower1, Upper, X) :-
   Lower1 < Upper,
   Lower2 is Lower1 + 1,
   between(Lower2, Upper, X).

我不明白为什么需要递归。 between 的逻辑定义可以是:

between(Lower, Upper, Something):-
   Lower =< Upper,
   Lower =< Something,
   Something =< Upper.

我在 gprolog 上尝试过,它有效,但仅适用于简单查询:

| ?- between(0,5,1).

yes

对于带有变量的查询,我得到:

| ?- between(0,5,X).
uncaught exception: error(instantiation_error, (=<)/2)

我不太明白为什么。

我觉得 Prolog 需要某种参考编号来统一变量,但为什么 (=<)/2 上的神秘错误?

一旦您知道 Prolog 中的通用算术 是做什么的,错误就不是那么神秘了。简而言之,它只是用来做 non-logical、"calculate this and give me the answer" 之类的算术运算。比较(所以所有 </2=</2=:=/2 等)要求你在两边都有 算术表达式is/2 假设它左边是一个算术表达式,右边是一个自由变量。因此,您可以执行以下操作:

?- X is 3^1.3.
X = 4.171167510947728.

?- 1 =:= sin(pi/2).
true.

如果你真的仔细阅读了GNU-Prolog手册,你应该会发现,在relevant section的开头,有下面两句话:

An arithmetic expression is a Prolog term built from numbers, variables, and functors (or operators) that represent arithmetic functions. When an expression is evaluated each variable must be bound to a non-variable expression.

(强调我的)

between/3plus/3succ/2 等谓词是 特殊用途整数算法 的示例。他们有他们的用途。然而,大多数用于进行实际整数数学运算的用途已被 CLPFD 取代。对于 GNU-Prolog,你应该 consult the documentation,但举个简短的例子,要模拟 between/3,你可以说:

?- fd_domain(X, 0, 2), fd_labeling(X).
X = 0 ? ;
X = 1 ? ;
X = 2
yes

你应该注意到这绝对是不是递归的(回答标题中的问题)。当然,我们都知道在某种程度上,为了得到这些答案,涉及到递归或迭代。