N爲N1 + 1,因爲這些變量從不統一。
我認爲你的意思是說他們永遠不會實例化,即他們永遠不會獲得價值。統一兩個變量可以實例化它們,但不是必需的。例如,你可以在一個序言REPL運行此:
?- N = N1.
N = N1.
而N
和N1
沒有任何價值(還),他們都是統一;如果N1稍後被實例化,則N將被實例化爲具有相同的值。另一個不那麼瑣碎,例如:
?- [H|T] = L, L = [1|M], writeln(H).
1
H = 1,
T = M,
L = [1|M].
但是,這是事實,N
不會與N1+1
統一! is
將評估N1+1
和這值將與N
統一。後內size([b,c,d],N1)
進行了評估,因此N1
變量將被實例會發生這種情況。
從本質上講,執行將是這樣的:
size([a,b,c,d],N).
size([b,c,d],N1)
size([c,d],N1)
size([d],N1)
size([],0)
N is 0+1.
N is 1+1.
N is 2+1.
N is 3+1.
這是一個有點低效的,因爲我們需要保留所有的函數調用內存;看看尾部遞歸和累加器來解決這個問題。
還要注意的是N1
需要,只是因爲is
是要計算表達式被實例化。你可以寫這樣的事情:
size([],0).
size([_|T], 1+ N1):-size(T,N1).
,如果你把它叫做:
?- size([1,2],N).
N = 0+1+1.
樂趣,不是嗎?您可能需要評估最後一個N,例如將其稱爲size([1,2],N), Result is N
。但是,一個問題是,我們在內存中保留了一個可以變得非常快的0+1+1+1+1+......
鏈。所以最好將這個技巧用於不會增長的事物,例如表達模板。
''''評估時,'**'肯定是統一的,因爲''執行從左到右,遞歸調用綁定'N' - 最終通過統一(本地版本)用'0'表示。 –
感謝您的快速回復。我不確定我是否明白你的意思。跟蹤過程中的哪個N與0統一? – JmanxC
我自己解決了問題:首先統一'N1',或者使用'0'或者從大小([H | T],N)'中的低級'N'',然後使用N1來計算頂層'N'。訣竅是瞭解在遞歸算法中,*有幾個不同版本的'N',每個版本都有不同的值*。在你的例子中,這些不同的'N'將被綁定到0,1,2,3和4. –