私は次のプロローグコードのスニペットを持っています:
num(0).
num(X) :- num(X1), X is X1 + 1.
fact(0,1) :-!.
fact(X,Y) :- X1 is X-1, fact(X1,Y1), !, Y is Y1 * X.
fact(X) :- num(Y), fact(Y,X).
次のコマンドがスタックオーバーフローを引き起こす理由を誰かが説明できますか?前もって感謝します。
fact(6).
私は次のプロローグコードのスニペットを持っています:
num(0).
num(X) :- num(X1), X is X1 + 1.
fact(0,1) :-!.
fact(X,Y) :- X1 is X-1, fact(X1,Y1), !, Y is Y1 * X.
fact(X) :- num(Y), fact(Y,X).
次のコマンドがスタックオーバーフローを引き起こす理由を誰かが説明できますか?前もって感謝します。
fact(6).
まずはルールを確認
num(0).
num(X) :- num(X1), X is X1 + 1.
述語num(Y)
は に対してすぐに有効になりY = 0
ます。
したがって、ルール
fact(X) :- num(Y), fact(Y,X).
次のように簡略化できます
fact(X) :- fact(0,X).
の一致が見つかりますfact(0,1)
。の場合X = 6
、代わりに起こることは、 の述語を定義するルールがないためfact(0,6)
、 で検索が開始されfact(-1,V1)
、その後にetc が続きます...ローカル結果が見つかった Var であるfact(-2,V2)
a に一致するまで。fact(-value, Var)
これは発生せず、エラーがトリガーされるまで無限ループがスタック全体を消費します。
fact(6)
が終了しない理由は、次のfailure-slice にあります。
?-事実(6)。num(0) :- false。 数値(X) :- num(X1), false ,X は X1 + 1. 事実(X) :- num(Y), false ,fact(Y,X).
このフラグメントは終了しないため、元のプログラムも終了しません。非終了はfact/2
!の定義とは無関係であることに注意してください。せいぜい、あなたのプログラムは成功するかもしれませんが、(限りなく) 失敗することはありません。
の別の定義fact/2
を使用することを検討してください。fact(N, 6).