2つの問題があります。is
最初の本当の問題は、次の代わりに使用する必要があるということです=
。
H is X-1
これは、算術評価をトリガーするために必要です。2番目の問題は実際の問題ではありませんが、より大きな誤解を招きます。H
それNextX
はそれと同等です。Prologにはバインディングのみがあり、「割り当て可能」はありません。したがって、同じバインディングで2つの「変数」を実際に作成する必要はありません。後で変更するために保持されている状態はありません。
両方をクリーンアップすると、次のようになります。
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.
これはおそらく本当に驚くべき見た目です。Xが変数か何かであることに気付いたので、どういうわけかPrologは式を維持するのに十分賢かったと思うかもしれませんが、それも真実ではありません。
?- 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.
実際には、算術演算で多くの推論を行う必要がある場合は、整数または実数のどちらに関心があるかによって、clpfd
またはそれに応じてライブラリを使用することをお勧めします。clpqr
このライブラリを使用すると、特定の範囲の値に対して方程式が成り立つように指定してそれらの値を取得するなど、より興味深いことをより簡単に行うことができます。