2017-01-21 33 views
1

我編寫了一個程序來對符號中的數字進行排序,它能正常工作,但給了我一個列表末尾的內存地址,它並沒有經過最後一次。爲什麼?SWI-Prolog列表末尾沒有實例化的變量

separate([],[],[]). 
separate([X],X,_):-number(X). 
separate([X],_,X). 
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S). 
separate([X|Y],Z,[X|S]):-separate(Y,Z,S). 

?- separate([3,a,b,4,5,c],X,Y).

諮詢我得到:

X = [3, 4, 5|_G2592], 
Y = [a, b, c] . 
+0

在看到答案後按下「Enter」鍵,如果按空格鍵會發生什麼情況。請參閱:[爲什麼SWI-Prolog只給我第一個答案?](http://stackoverflow.com/q/34463248/1243762) –

+0

它也有助於在第一次學習Prolog時不使用像'X'和'Y這樣的變量'但更有意義的名稱,如數字,字母,數字,字母,休息。一旦你明白髮生了什麼,那麼你可以回到'X'和'Y'等。 –

回答

1

那是因爲你留下您的清單尾巴開放

 
separate([X],X,_):-number(X). 
separate([X],_,X). 

的事情是:你其實並不需要寫這些語句,你可能會忽略它們:

separate([],[],[]). 
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S). 
separate([X|Y],Z,[X|S]):-separate(Y,Z,S). 

這本來可以工作的但它會返回多個結果,除第一個,其餘都是錯誤的。你應該通過增加一個後衛最後一句話,解決這個問題:

 
separate([],[],[]). 
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S). 
separate([X|Y],Z,[X|S]):-\+ number(X),separate(Y,Z,S). 

\+的作用就像一個「不」在這個意義上\+ number(X)如果將序言無法比擬number(X)成功。

最後要說明的是,你所看到的並不是一個真正的內存地址:它只是一個沒有實際意義的變量,儘管這當然是一個小小的評論。

+0

不確定它是否是一個內存地址,但它是我認爲最接近的,謝謝你清理它太。 \ +對我來說是未知的,並且在我們的腳本中從未被提及過。 – Streamline

+0

@Streamline:啊'\ +'就像一個「不」(儘管說這很危險)。如果Prolog未能匹配「數字(a)」,那麼它就不是一個意思,「\ + number(a)」將會成功。 –

2

我建議

separate([],[],[]). 

separate([H | T], [H | Tn], Ls) :- 
    number(H), 
    separate(T, Tn, Ls). 

separate([H | T], Ln, [H | Ts]) :- 
    \+ number(H), 
    separate(T, Ln, Ts). 

如果你有一個終端子句separate([],[],[])和一些普通條款,如separate([X|Y],[X|Z],S)separate([X|Y],Z,[X|S]),你不需要半途minal子句爲separate([X],X,_)separate([X],_,X),並且它們(未定義的值爲_)避免統一其中一個列表,並獲得「內存地址」(非統一變量的標識符)。

如果你有一個條款與number(X),其他(替代)條款需要「非數字」檢查(即\+ number(X)),否則這兩個條款對數字是真實的,你乘以解決方案,列表中的數字不是數字。