使用Lisp中的cons函数问题?

时间:2014-02-19 14:44:42

标签: lisp append

我正在学习Lisp,我必须编写一个函数,其返回值是一个包含给定输入中奇数整数(如果有)的列表。在代码中我有这个:

(defun f3 (a)
   (cond
    ((null a) nil )
    ((and (numberp (car a)) (oddp (car a))) (cons (car a) (f3 (cdr a))))
    (T (f3 (cdr a)))
   ) ; end cond
)

我原本想使用追加功能,但我一直都会遇到错误。

建议我使用cons功能。当我这样做时,我的功能开始工作(代码在上面)。我最初有这个:

(defun f3 (a)
    (cond
       ((null a) ())
       ((and (numberp (car a)) (oddp (car a))) (append (f3 (cdr a)) (car a))))
       (T (append () (f3 (cdr a))))
    )
)

但不断出错。例如,如果我调用(f3 '(1 2 3)),它会说“错误3不是类型列表”。所以,我的问题是为什么利弊在这里起作用,为什么追加不起作用?利润如何运作?提前谢谢。

3 个答案:

答案 0 :(得分:6)

append需要列表参数,(car a)不是列表。而不是(car a)您需要(list (car a))。换句话说,(append (f3 (cdr a)) (list (car a)))

这基本上可行,但你会得到相反顺序的结果。那应该是(append (list (car a)) (f3 (cdr a)))

另请注意,您的(append () (f3 (cdr a)))仅相当于(f3 (cdr a))

原始版本的更改将是:

(defun f3 (a)
    (cond
       ((null a) ())
       ((and (numberp (car a)) (oddp (car a))) 
          (append (list (car a)) (f3 (cdr a)))))
       (T (f3 (cdr a)))))

但是,通常不会使用append将单个元素添加到列表中。使用cons更自然地完成。所以

  (append (list (car a)) (f3 (cdr a)))

通过以下方式更恰当地完成:

  (cons (car a) (f3 (cdr a)))

最终将您带到您展示的工作版本。

答案 1 :(得分:5)

虽然类似mbratch's answer之类的内容可以帮助您了解列表操作(因此在您的研究中对您来说可能是一个更有用的答案),但学习它也很重要关于您正在使用的语言的标准库。在这种情况下,您试图过滤除奇数之外的所有内容。使用remove-if-not,这只是:

(defun keep-odd-numbers (list)
  (remove-if-not (lambda (x)
                   (and (numberp x) (oddp x)))
                 list))
CL-USER> (keep-odd-numbers '(1 a 2 b 3 c 4 d 5 e))
;=> (1 3 5)

答案 2 :(得分:1)

虽然这不是@mbratch提供的实际问题的解决方法,但这是使用LOOP宏(标准库的另一部分)实现类似内容的方式:

(defun keep-odd-numbers (list)
  (loop for x in list collecting x when (and (numberp x) (oddp x))))