Prologクエリ:再帰クエリの追加はどのように重要ですか
リストのn番目の要素を見つけるための述語を書き込もうとしています。
最初に私はこのようなものを書きました:
nth([X|_], 0, X).
nth([_|T],N,Z):- N > 0, nth(T, M, Z), N is M + 1.
のようなクエリでは機能しますnth([1, 2, 3, 4, 5], 0, X).が、のようなクエリではnth([1, 2, 3, 4, 5], N, 1).、「;」を入力すると「引数のインスタンス化が不十分なエラー」が発生します。答えを得た後。この場合、回答は1つしかないことはわかっていますが、完全を期すために、その理由を知りたいと思います。
私はここでスタックオーバーフローについて読んだところ、以下がより良い解決策であることがわかりました:
nth([X|_], 0, X) :- !.
nth([_|Y], N, Z) :- N > 0, M is N-1, nth(Y, M, Z).
私の答えとは対照的に、なぜM is N-1, nth(Y, M, Z).違いが生じるのかを理解したいとnth(T, M, Z), N is M + 1思います。
PS:質問のタイトルは改善できると思いますが、どうすればよいかわかりません。あなたが提案があれば、私に知らせてください!
回答
is/2完全な制約ソルバーではありません。したがってN is M + 1、M is N - 1同等に見えますが、そうではありません。1つ目は、Mがインスタンス化されたときにのみ成功し、2つ目はNがインスタンス化されたときに成功します。他のゼロのインデックスを使用してソリューションを試しましたか?それらは機能しません。plus(1, M, N)どちらかを使用する代わりに使用して、機能させることができます。また、句の順序も重要なのでplus(1, M, N)、への再帰呼び出しの前に行う必要がありますnth。
nth([X|_], 0, X).
nth([_|T],N,Z):- N > 0, plus(1, M, N), nth(T, M, Z).
N > 0, nth(T, M, Z), plus(1, M, N)が句の順序である場合、Mはまだインスタンス化されていないため、プログラムはnth(T, M, Z)最初に満たそうとし、でN > 0インスタンス化されていないエラーを引き起こします。
また、どちらのプログラムも生成的なケースでは機能しません。