2012-04-18 77 views
1

我要創建例如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,[]). 

回答

6

如果你想從1創造的連續編號的列表,以N,你就可以使用內置的謂詞findall/3between/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]. 
+1

或者只是使用numlist/3。 – mat 2012-04-18 13:07:06

+0

@mat:你說得對,更新了答案以顯示更好的替代方案 – gusbro 2012-04-18 13:14:05

2

您的代碼有三個問題。第一個問題是,您將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). 
+1

'do_list(1,[])怎麼樣?' – false 2012-04-18 13:34:40

+1

你有一種奇怪的能力來發現隱式使用模式引起的問題!我已經爲第二個條款添加了一個測試來避免這個問題。感謝您指出。 – twinterer 2012-04-18 13:43:54

+0

你現在也修正'do_list(-1,L)'。順便說一句,哪些系統不需要這個'!'? – false 2012-04-18 13:53:25

0

或者如果你不想使用任何內置函數(像我一樣,當我嘗試這種做法,然後遇到這個問題),你可以使用這個(工作但不是有效的)解決方案:

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僅適用於正整數。