2015-09-04 106 views
3

我需要實現函數,該函數根據傳遞給函數的參數創建一個列表。函數意外的結果(遞歸)

這裏是我的代碼:

(defun lstbuilder (&rest args) 
    (if (eq (car args) NIL) 
     NIL 
     (cons (car args) 
      (lstbuilder (cdr args))))) 

此功能無法正常工作。 結果:

(lstbuilder 'a 'b 'c 'd 'e) ;expected (a b c d e) 
(a (b c d e)) ;result 
+0

任何你沒有以更簡單的方式實現它的原因((defun lstbuilder(&rest args) args)' – PuercoPop

回答

4

你需要才能使用(apply #'lstbuilder (cdr args))到「圖示」列表中的內容作爲函數調用的參數。

+0

謝謝。你能告訴我如何從函數返回這個列表嗎? –

+0

「傳入的&rest參數列表已經是新分配的列表。」其實,它*不一定是新鮮分配的清單。使用APPLY調用的函數的&rest參數的值可以與APPLY的列表參數共享結構。具體而言,[HyperSpec for APPLY](http://www.lispworks.com/documentation/HyperSpec/Body/f_apply.htm)說: –

+1

「當函數通過&rest接收其參數時,它是允許的(但不是必需的)對於實現來說,將其餘參數綁定到與最後一個參數共享結構的對象上,因爲函數既不能檢測它是否通過apply調用,也不能檢測(如果是)最後一個參數是常量,**符合的程序既不依賴於清單列表的結構,也不必修改該列表結構。**「 –

5

風格

  • 請使用標準的Lisp格式。使用編輯器將幫助您縮進Lisp代碼。

  • 不要只在一行上放置括號。這只是浪費空間沒有好處。

  • 更長的名字得到一個-之間的字:list-builder

  • 請勿使用carcdr進行列表操作。使用firstrest

  • 列表測試的結束是endp

例子:

(defun list-builder (&rest args) 
    (if (endp args) 
     nil 
    (cons (first args) 
      (apply #'list-builder (rest args))))) 

由於args變量已經是一個名單,我們就可以把它複製:

(defun list-builder (&rest args) 
    (copy-list args)) 

或者我們可以重用list功能,這已經創造其參數列表:

(setf (symbol-function 'list-builder) 
     #'list) 
+0

小小的挑剔,我認爲如果按照elisp風格縮進,而不是普通的lisp,隨之而來的是更多的縮進。 – PuercoPop

+2

@PuercoPop:實際上這是LispWorks中的默認縮進樣式。 –

+1

我不知道。我想知道爲什麼,在elisp中,這是因爲else子句被包含在外部的progn中,所以這是理由 – PuercoPop