2015-09-04 78 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