我要創建例如n個元素的列表,Prolog的創建列表
do_list(5,L1).
應該返回,
L1=[1,2,3,4,5].
這是我有什麼,但它不工作。
do_list(X,L1):- X1 is X-1, do_list(X1,[X1|L1]).
do_list(0,[]).
我要創建例如n個元素的列表,Prolog的創建列表
do_list(5,L1).
應該返回,
L1=[1,2,3,4,5].
這是我有什麼,但它不工作。
do_list(X,L1):- X1 is X-1, do_list(X1,[X1|L1]).
do_list(0,[]).
如果你想從1創造的連續編號的列表,以N,你就可以使用內置的謂詞findall/3
和between/3
這樣:
do_list(N, L):-
findall(Num, between(1, N, Num), L).
?- do_list(5,L).
L = [1, 2, 3, 4, 5].
SWI也有另外一個內建,就是這樣,numlist/3
:
?- numlist(1,5,L).
L = [1, 2, 3, 4, 5].
您的代碼有三個問題。第一個問題是,您將X1添加到子句體中的列表中,但是您絕不會將新列表傳遞迴子句的頭部。即,L1是一個累加器變量,但是你需要第三個參數,它將被綁定到最終列表。
第二個是第二個子句只在輸入列表爲空時匹配。這絕不會是這種情況,因爲您在遞歸調用do_list/2
之前將X1添加到列表中。即,您沒有遞歸錨點,並且目標?- do_list(5,L)
將永遠不會返回。
第三個問題是,您將X1添加到列表而不是X.您會跳過最大的數字。
這是它應該是如何工作的:
do_list(N, L) :- do_list1(N, [], L).
do_list1(0, L, L) :- !.
do_list1(N, R, L) :- N > 0, N1 is N-1, do_list1(N1, [N|R], L).
或者如果你不想使用任何內置函數(像我一樣,當我嘗試這種做法,然後遇到這個問題),你可以使用這個(工作但不是有效的)解決方案:
connect([],X,X).
connect([H|T],C,[H|T2]) :- connect(T,C,T2).
revert([],[]).
revert([H|T],R) :- revert(T,Trev), connect(Trev,[H],R)
do_revlist(0,[]).
do_revlist(X,[X|L]) :- X1 is X-1, do_revlist(X1,L).
do_list(X,L2) :- do_revlist(X,L), revert(L,L2).
PS僅適用於正整數。
或者只是使用numlist/3。 – mat 2012-04-18 13:07:06
@mat:你說得對,更新了答案以顯示更好的替代方案 – gusbro 2012-04-18 13:14:05