私はプロローグでかなり錆びていますが、なぜこのようなことが失敗するのかわかりません:
frack(3).
frack(X) :- frack(X-1).
したがって、frack(4) を評価するとします。上記の事実が定義された対話型プロンプトから、4-1 = 3 であるため、無限に再帰する必要はないと思います。しかし、SWI-Prolog で次のエラーが発生します。
ERROR: Out of global stack
私はプロローグでかなり錆びていますが、なぜこのようなことが失敗するのかわかりません:
frack(3).
frack(X) :- frack(X-1).
したがって、frack(4) を評価するとします。上記の事実が定義された対話型プロンプトから、4-1 = 3 であるため、無限に再帰する必要はないと思います。しかし、SWI-Prolog で次のエラーが発生します。
ERROR: Out of global stack
これが、この非終了の理由です。終了しないプログラムの失敗スライスがあるため、クエリは終了しません。
?- frack(4)。frack(3) :- false。 フラック(X) :- frack(X-1), false .
これは、表示されている部分を変更することによってのみ修正できます。3 つの SO 回答は、 を使用することを提案しています(is)/2
。しかし、これは非終了を削除しません! 実際、 を使用(is)/2
すると、本質的に同じフラグメントにつながります。
?- frack(4)。frack(3) :- false。 フラック(X) :- Y は X - 1、 frack(Y), false .
少なくとも、frack(4)
今は成功しますが、バックトラックでループします。X
非終了を避けるために、のテストのように、目に見える部分で何かを変更する必要があります。詳細については、 failure-sliceを参照してください。
それを試してみてください:
?- 4-1 = 3.
false.
なんで?なぜなら4-1 = -(4, 1)
、これは明らかに数ではなく複合項だからです。
Prolog で整数について推論するには、たとえば (GNU Prolog または B-Prolog を使用して) clpfd制約を使用します。
| | ?- 4-1 #= X. X = 3
SWI-Prolog では、グラフィカル トレーサーが何が起こるかを確認するのに役立つ場合があります。
?- gtrace, frack(4).
より複雑なデバッグについては、 false's answerに示されているように、失敗スライスをお勧めします。
frack(X) :- frack(X-1).
する必要があります
frack(X) :- Y is X - 1, frack(Y).
あなたがそれを書いた方法X-1
では、最初のレベルの表現は次のレベルの変数と統合され、事実X
に決して行きません。frack(3)
is演算子を使用しない限り、Prologは算術演算を行いません。
frack(X) :- X1 is X-1, frack(X1).