質問

私はアキュムレーターが何であり、それらが何をしているのかについてのチュートリアルを探していましたが、すべての説明は非常に複雑であるように思われ、それを利用できるようにそれらがどのように機能するかについての十分な絵を本当に教えてくれません。蓄積者は、他のコードによって呼び出されて変更されるような数などのものを保持していることを理解しているようです。問題は、アキュムレータが何であるかを理解していて、いつ必要なのかを知っていることですが、実際に使用する方法がわかりません。

私が見たチュートリアルから、アキュムレータが空のリストのように見えることもありますが、それ以外の場合は「0」と思われることもあります。誰かが私に簡単な言葉で説明してもらえますか?

また、私の質問の第2部では、プロログコードでこれをよく使用している人々に気づいたようです。

\+member

リストに何かをするコードの行の中で常に使用されているのを常に見ているので、リストと関係があると推測することができましたが、周りを検索した後、 +メンバーは実際に意味するのは「失敗としての否定」であることがわかりました。 - 証明できませんが、これが何を意味するのか、あるいはその人が正しかったとしても本当に理解していません。繰り返しになりますが、誰かが私に正確に何をしているのか、そしてあなたの説明をシンプルにしようとしている間、それが何を使うことができるかを説明してもらえますか?

これら2つの問題に関する助けをありがとう。

役に立ちましたか?

解決

初め、 \+ 目標の否定です。それに続く目標が失敗すると、それは成功します。例えば:

?- member(3, [1,2,3]). # 3 is a member of the List
true.

?- member(4, [1,2,3]). # 4 is not a member
false.

?- \+member(4, [1,2,3]). # succeeds, because 'member' fails
true.

?- \+member(3, [1,2,3]).
false.

?- atom_chars('hi', C).
C = [h, i].

?- atom_chars('hi', [h, i]).
true.

?- atom_chars('hello', [h, i]).
false.

?- \+atom_chars('hello', [h, i]).
true.

第二に、アキュムレータは、尾の再帰の最適化を活用するために、再帰を介して状態を通過する方法です。

因子を計算するこれら2つの同等の方法を考えてみましょう。

?- [user].
|: fact_simple(0, 1).
|: fact_simple(N, F) :- 
         N1 is N-1, 
         fact_simple(N1, F1), 
         F is N*F1.
|: % user://2 compiled 0.00 sec, 440 bytes
true.

?- fact_simple(6, F).
F = 720 .

[user].
|: fact_acc(N, F) :- fact_acc(N, 1, F).
|: fact_acc(0, Acc, Acc).
|: fact_acc(N, Acc0, F) :- 
         N1 is N-1, 
         Acc is Acc0 * N, 
         fact_acc(N1, Acc, F).
|: % user://4 compiled 0.00 sec, 1,912 bytes
true.

?- fact_acc(6, F).
F = 720 .

最初のバージョンは、再帰でそれ自体を呼び出すだけで、サブコールが完了するのを待ちます。その場合にのみ、それはそれを掛けます N-SubCallの結果との価値。

2番目のバージョンは代わりにアキュムレータを使用します(Acc)。ご了承ください 1 アキュムレータではありませんが、初期値です。その後、Predicateへの各呼び出しは次のとおりです N- アキュムレータとの価値と再帰が基本ケースに達すると、アキュムレータの値はすでに最終値です。

問題は、実際には「アキュムレータは何であるか」ではありませんか? (0または空のリストなど)。それは単なる「あなたが行くように」値を蓄積する方法であり、呼び出しの述語に戻らないことです。これにより、Prologシステムは、増え続けるコールスタックを構築する必要はありません。

ただし、この例では、乗算の順序が自然に逆になっていることに注意してください。増殖することは関係ありませんが、他の値(リストなど)については、それを処理する必要があります。

fact_simple 乗算は行われました 1 * 2 * 3 * 4 * 5 * 6, 、 その間 fact_acc それを持っていた 1 * 6 * 5 * 4 * 3 * 2. 。それが不明な場合は、両方のトレースをするだけです!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top