我試圖找出這個問題,但沒有成功 你能告訴我什麼是錯?序言deleteall不起作用
% using accumulator
deleteall(X,Y,Zs) :- deleteall(X,Y, [], Zs).
deleteall(X, [], Zs, Zs).
deleteall(X, [X|Xs], Xs, V).
deleteall(X, [Y|Xs], [Y|Zs], V) :- deleteall(X, Xs, Zs,V).
我試圖找出這個問題,但沒有成功 你能告訴我什麼是錯?序言deleteall不起作用
% using accumulator
deleteall(X,Y,Zs) :- deleteall(X,Y, [], Zs).
deleteall(X, [], Zs, Zs).
deleteall(X, [X|Xs], Xs, V).
deleteall(X, [Y|Xs], [Y|Zs], V) :- deleteall(X, Xs, Zs,V).
辛格爾頓變量總是疑神疑鬼,對你來說,什麼是V的含義deleteall(X, [X|Xs], Xs, V).
?
除此之外,我不明白你爲什麼使用累加器。
您是否分配了未被刪除的元素?否則,這裏是工作可以用deleteAll ...
deleteall(_, [], []).
deleteall(X, [X|Xs], Zs) :- !, deleteall(X, Xs, Zs).
deleteall(X, [Z|Xs], [Z|Zs]) :- deleteall(X, Xs, Zs).
測試:
?- deleteall(2,[1,2,3,54,2,1,4,2],X).
X = [1, 3, 54, 1, 4] ;
false.
從你的代碼,它似乎想要基於統一deleteall語義(另一種是刪除只使用(==)/ 2)相等的術語。是否所有的列表元素(以及您想要刪除的元素)總是在地面上?如果不是,那麼只要您想要刪除的元素被部分實例化,並且在與其中一個列表元素統一時進一步實例化,您的代碼就會失敗。您可以通過使用例如雙重否定在身體而不是頭統一。正如「chac」已經指出的那樣,你也離開了選擇點。使用cut或if-then-else解決了這個問題。改進代碼的另一種方法是將列表移動到第一個參數,從而允許Prolog的第一個參數索引爲您提供更好的性能(當然,假設對謂詞的調用將實例化第一個參數)。遵循以下這些定義:
delete_all([], _, []).
delete_all([X|Xs], Y, Zs) :-
( \+ X \= Y ->
delete_all(Xs, Y, Zs)
; Zs = [X|Zs0],
delete_all(Xs, Y, Zs0)
).
對於純粹的解決方案,請考慮this answer – note the different argument order。
但實際的問題是:什麼是錯你解決方案?
有一種方法,其方式是獨一無二的Prolog的回答這個。在其他編程語言中,你必須找出有意義的測試用例。然後,您將使用這些測試用例來查看您的實現是否有效。當然,在Prolog中也是如此。
不過想想實際成本弄清楚這些測試用例!你必須全面瞭解整個關係。你將不得不精心打印精神上存在的數據結構。這是相當智力的努力。你的例子非常簡單,所以這個努力似乎很小。但想象一下在這裏和那裏添加的更多細節。
那麼怎樣才能找出一個測試用例謂語不理解實際的關係?
只需採取最一般的查詢。也就是說,在所有參數中都有一個具有不同變量的目標對於你的例子,那將是deleteall(X, Xs, Ys)
。現在,我們的工作已經完成,我們可以讓Prolog填補空白。
?- deleteall(X,Xs,Ys). Xs = Ys, Ys = [] ; Xs = [X] ; false.
根據您的定義,我們得到兩個答案。第一個答案包含Xs
爲空列表[]
的解決方案。第二個答案包含Xs
是一個元素列表的解決方案。這就是你所有的關係描述。
包含兩個或更多元素的列表如何?他們沒有解決方案。所以,你的定義在這方面太具體了。
第二個答案適用於所有Ys
。例如。根據你的定義,deleteall(1,[1],[2,3])
也保留–。更糟糕的是:deleteall(1,[1],[1]).
根本沒有刪除。所以你的定義太籠統了。
這是怎麼回事?那麼,你必須編寫純粹的單調程序。也就是說,不得使用不完整的內置插件,如!/0
,(\+)/1
,(\=)/2
,(\==)/2
,並且不得使用(或非常特別小心地使用)內置插件。