1

我正在尝试编写一个函数 -它按降序decListRange(X,List)给出范围内的列表。[X-1:1]例如 -
decListRange(9,List).

会给 -

List = [8,7,6,5,4,3,2,1].

我尝试了以下但它进入无限循环 -

decListRange(1,[]) :- !. 
decListRange(X,[H|Rest]) :-
    H  = X-1, NextX = X - 1 ,decListRange(NextX,Rest).
4

1 回答 1

2

你有两个问题。第一个真正的问题是您需要使用is而不是=

H is X-1

这是触发算术评估所必需的。您的第二个问题不是真正的问题,而是说明了一个更大的误解,那就是H并且NextX是等效的。因为 Prolog 只有绑定而不是“可赋值”,所以您永远不需要创建两个具有相同绑定的“变量”。没有保留状态供您以后修改。

清理两个你得到这个:

decListRange(1, []) :- !.
decListRange(X, [H|Rest]) :-
  X > 1,
  H is X-1,
  decListRange(H, Rest).

编辑 2:clpfd 实现

:- use_module(library(clpfd)).

declist(N, L) :- N == 1, !, L = []. % green cut
declist(1, []). 
declist(N, [N1|Ns]) :- 
  N #> 1, 
  N1 #= N - 1, 
  declist(N1, Ns).

这个具有@false 在评论中提到的属性:

?- declist(3, L).
L = [2, 1] ;
false.

?- declist(3, [2,1]).
true ;
false.

?- declist(N, [3,2,1]).
N = 4.

?- declist(N, X).
N = 1,
X = [] ;
N = 2,
X = [1] ;
N = 3,
X = [2, 1] ;
N = 4,
X = [3, 2, 1] ;
N = 5,
X = [4, 3, 2, 1] .

编辑=:关于和之间区别的简短插曲is

在过程语言=中,几乎总是将特定值分配给变量的语法。在 Prolog 中,变量是绑定,一旦建立,就不能通过重新分配不同的值来直接修改它们。相反,它们更像数学和逻辑中的变量,其中变量“代表”有趣的值,但这些值本身基本上是不可变的。在 Prolog 中,=本质上是要求统一引擎建立绑定。因此,如果您要执行以下操作:

?- name(X, Y) = name(bob, tony).

Prolog 以变量绑定响应:

X = bob,
Y = tony.

一旦存在这些绑定,矛盾的绑定将失败,而肯定的绑定将成功:

?- name(X, Y) = name(bob, tony), X = bob.
X = bob,
Y = tony.

?- name(X, Y) = name(bob, tony), X = william.
false.

统一算法本身对算术一无所知。这具有令人愉快的副作用,您可以使用任何原始表达式。例如:

?- Expr = X + 3, Z + Q = Expr.
Expr = Z+3,
X = Z,
Q = 3.

这可能真的很令人惊讶。你可能会期望 Prolog 足够聪明地保留表达式,因为它注意到 X 是一个变量或其他东西,但这也不是真的:

?- X = 4, Expr = X + 3, Z + Q = Expr.
X = 4,
Expr = 4+3,
Z = 4,
Q = 3.

另一种看待这一点的方式是,Prolog 认为+只是另一个运算符,所以这样X+3的事实add(X, 3)并不一定有任何特殊含义。无论您以哪种方式看待它,is/2运算符的存在都是为了应用算术推理并产生一个值:

?- X = 4, Expr is X + 3.
X = 4,
Expr = 7.

请注意,Expr 具有计算值,但没有原始结构:

?- X = 4, Expr is X + 3, Z + Q = Expr.
false.

在实践中,如果您需要对算术进行大量推理,您将需要使用类似clpfdclpqr取决于您是否对整数或实数感兴趣的库。该库使您能够更轻松地做更多有趣的事情,例如指定一个方程对某个范围内的值成立并取出这些值。

于 2013-01-17T18:53:52.113 回答