2

ここにプロローグコードがあります(私はこれに従っています)。

len([],0).
len([_|T],N) :- len(T,X), N is X+1.

ここにそのトレースがあります(Linux、swiを実行しています)

    [trace]  ?- len([d,f,w,c],X).
   Call: (7) len([d, f, w, c], _G314) ? 
   Call: (8) len([f, w, c], _L182) ? 
   Call: (9) len([w, c], _L201) ? 
   Call: (10) len([c], _L220) ? 
   Call: (11) len([], _L239) ? 
   Exit: (11) len([], 0) ? 
^  Call: (11) _L220 is 0+1 ? 
^  Exit: (11) 1 is 0+1 ? 
   Exit: (10) len([c], 1) ? 
^  Call: (10) _L201 is 1+1 ? 
^  Exit: (10) 2 is 1+1 ? 
   Exit: (9) len([w, c], 2) ? 
^  Call: (9) _L182 is 2+1 ? 
^  Exit: (9) 3 is 2+1 ? 
   Exit: (8) len([f, w, c], 3) ? 
^  Call: (8) _G314 is 3+1 ? 
^  Exit: (8) 4 is 3+1 ? 
   Exit: (7) len([d, f, w, c], 4) ? 
X = 4.

プロローグがこれらの「ツリー」を実行していることは知っていますが、変数のインクリメントが終了時にのみ行われる理由を理解するのに苦労しています-これの仕組みの説明はありますか?

どうもありがとう!

4

1 に答える 1

6

その理由は、それN is X+1が述語の最後の部分だからです。

次のように考えてください: を計算するには、 を呼び出すことによって計算されるN is X+1の値を知る必要があります。しかし、計算のプロセスでは、空のリストになってしまう状況まで、へのさらに別の呼び出しが必要です。Xlen(T,X)Xlen

その時点で、リストの長さ、つまり 0 が判明します。したがって、その値が「返されます」。そうして初めて、0 + 1 を計算して「返す」ことができます。そして 1 + 1 など。

別の見方をすると、任意の 2 つの述語aandbについて、とa, bの両方が true の場合に true が返されることに注意してください。Prolog では、が trueであることがわかっている場合にのみ評価されます (それ以外の場合は、結果が false であることがわかっているため、 を評価しても意味がありません)。abbab

その結果、すべての加算はへの再帰呼び出しのlenに行われます。

于 2009-11-19T12:45:14.657 に答える