因此,有很多事情要說。首先,就像在大多數聲明性語言中一樣,變量不能真正改變值。
這也就意味着,X = 1.
將統一1
到X
如你所期望的,但如果你在你的查詢(X = 1, X = 2.
)之後添加X = 2.
,Prolog的會說false
。其原因是你不能統一1
與2
和X
已真正成爲1
,因此X
不能統一爲2
。
儘管和Haskell,Ocaml等不同,您可以部分綁定一個變量,如X = h(Y).
。然後,您可以進一步將它統一爲X = h(a(Z)).
,而您不能以之前提到的語言(其中變量實際上只是值的別名)。
他爲什麼告訴我你想知道的一切?那麼,這是你的主要問題。您首先將X
綁定到[6, 5]
,然後期望進一步將其綁定到其他某些東西。一旦一個變量被研磨(即它本身不包含任何自由變量),就不能再次改變它的值。
所以這裏你的遞歸不會做任何事情,但最終會證明X
錯誤。但是,這並不是因爲您每次都會以相同的參數呼叫addToEnd/3
([6]
,[5]
和[6, 5]
)。
這就是說,讓我們看看我們如何可以改善您的代碼。
首先,一句話:
multiply(2, 3, Y),
A = Y ,
add(2, 3, Z),
B = Z,
addToEnd([A], [B], X),
可以寫
multiply(2, 3, Y),
add(2, 3, Z),
addToEnd([Y], [Z], X),
沒有丟失任何信息,因爲你不要再使用A
和B
。
現在,讓我們忘掉addToEnd/3
了一會兒,想想你想要什麼。
如果輸入s1(0, Q)
,你真的要Q
留免費的嗎?因爲那是你目前所說的。在這種情況下,綁定Q
到[]
會更有意義。另外,你會很快看到,這將成爲一個很好的遞歸基礎案例。
s1(0, []).
是一條捷徑說
s1(0, Q) :- Q = [].
因爲Prolog的確實條款頭統一(部分:-
之前)。
然後,我就騙一點,但它會只是留下清晰。你可以聲明打算從s1(4, Q)
到s1(5, Q)
當你想到Q可舉辦一些微積分的一個更大的價值。
在這裏,我們可以指出如下:
s1(N, [SomeCalculus|Q]) :-
PreviousN is N - 1,
s1(PreviousN, Q).
現在,我們只需要提供一個值SomeCalculus
:
s1(N, [SomeCalculus|Q]) :-
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
SomeCalculus = [X, Y],
s1(PreviousN, Q).
或者,如果您是正確的,我們可以直接寫:
s1(N, [[X, Y]|Q]) :-
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
s1(PreviousN, Q).
所以完整的程序將是:
現在
s1(0, []).
s1(N, [[X, Y]|Q]) :-
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
s1(PreviousN, Q).
,如果你測試,你可能此話的程序循環,就像你當你點擊;
關鍵。這是因爲序言認爲第二條款可以適用於0
了。
因此,讓我們再次修改程序:
s1(0, []).
s1(N, [[X, Y]|Q]) :-
N > 0,
PreviousN is N - 1,
X is 2 * 3,
Y is 2 + 3,
s1(PreviousN, Q).
現在一切都很好。
我希望這可以幫助您更好地理解如何通過遞歸構建適當的謂詞。我並沒有花太多時間來糾正你的謂詞,因爲我對變量的散漫應該已經告訴了你很多關於它的錯誤。
非常感謝這一點,它確實有幫助。道歉爲什麼我敢肯定的是我的代碼中的基本錯誤,我是新的prolog,並來自C,Java等,這是一個非常不同的思維方式。 – XavierNuquos 2012-04-08 09:40:17
@Mog:非常好!你真的有老師的天賦! – CapelliC 2012-04-08 10:48:38
@chac:謝謝:) – m09 2012-04-08 10:54:14