ですから、ここで言うことはたくさんあります。何よりもまず、ほとんどの宣言型言語と同様に、変数は実際には値を変更できません。
それが意味することは、それはあなたが期待X = 1.
するように統一1
されるということです、しかしあなたがあなたのクエリ()でその後に追加するならば、Prologは言うでしょう。その背後にある理由は、あなたが統一することができず、それが本当にになっているため、に統一することができないということです。X
X = 2.
X = 1, X = 2.
false
1
2
X
1
X
2
ただし、HaskellやOcamlなどとは異なりますが、のように部分的に変数をバインドできますX = h(Y).
。X = h(a(Z)).
そうすれば、前述の言語ではできなかったものの、それをさらに統合できるようになります(変数は実際には値の単なるエイリアスです)。
なぜ彼はあなたが不思議に思うことをすべて私に言うのですか?さて、それがここでのあなたの主な問題です。最初ににバインドX
し[6, 5]
、次にそれを他のものにさらにバインドすることを期待します。変数がグラウンドされると(つまり、その中に自由変数が含まれないと)、その値を再び変更することはできません。
したがって、ここでは、再帰は何もしませんが、最終的にはX
誤りであることがわかります。addToEnd/3
ただし、ここでは、毎回同じ引数(、、および)を使用し[6]
て[5]
呼び出すことになりますので、そうではありません[6, 5]
。
そうは言っても、コードを改善する方法を見てみましょう。
まず、コメント:
multiply(2, 3, Y),
A = Y ,
add(2, 3, Z),
B = Z,
addToEnd([A], [B], X),
書くことができます
multiply(2, 3, Y),
add(2, 3, Z),
addToEnd([Y], [Z], X),
A
何度も使用しないので、情報を失うことなくB
。
さて、ちょっと忘れてaddToEnd/3
、何が欲しいか考えてみましょう。
あなたが入った場合s1(0, Q)
、あなたは本当にQ
自由に滞在したいですか?それがあなたが現時点で述べていることだからです。その場合、バインドする方が理にかなってQ
います。[]
さらに、すぐにわかるように、これは再帰的なベースケースになります。
s1(0, []).
言うためのショートカットです
s1(0, Q) :- Q = [].
Prologは節の先頭(前の部分:-
)で統一を行うためです。
次に、少しごまかしますが、それはただ明確に保つことです。s1(4, Q)
から行くとき、s1(5, Q)
Qが微積分のもう1つの値を保持することを期待すると言うことができます。
ここでは、次のように述べることができます。
s1(N, [SomeCalculus|Q]) :-
PreviousN is N - 1,
s1(PreviousN, Q).
今、私たちはただに値を与える必要がありますSomeCalculus
:
s1(N, [SomeCalculus|Q]) :-
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
SomeCalculus = [X, Y],
s1(PreviousN, Q).
または、正しく従えば、次のように直接書くことができます。
s1(N, [[X, Y]|Q]) :-
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
s1(PreviousN, Q).
したがって、完全なプログラムは次のようになります。
s1(0, []).
s1(N, [[X, Y]|Q]) :-
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
s1(PreviousN, Q).
;
さて、それをテストすると、キーを押したときにプログラムがあなたと同じようにループすることに気付くかもしれません。これは、Prologが2番目の条項も適用できると考えているため0
です。
それでは、プログラムをもう一度編集しましょう。
s1(0, []).
s1(N, [[X, Y]|Q]) :-
N > 0,
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
s1(PreviousN, Q).
今、すべてが順調です。
これが、再帰を通じて適切な述語を構築する方法をよりよく理解するのに役立つことを願っています。addToEnd/3
変数についての私のとりとめのない話は、それの何が悪いのかについてすでに多くのことを教えてくれたはずなので、私はあなたの述語を修正するのに多くの時間を費やしませんでした。