使用Lisp中的cons函数问题?

Rob*_*b L 0 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
)
Run Code Online (Sandbox Code Playgroud)

我原本想使用append函数,但我一直都会遇到错误.

我建议使用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))))
    )
)
Run Code Online (Sandbox Code Playgroud)

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

lur*_*ker 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)))))
Run Code Online (Sandbox Code Playgroud)

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

  (append (list (car a)) (f3 (cdr a)))
Run Code Online (Sandbox Code Playgroud)

更合适的做法是:

  (cons (car a) (f3 (cdr a)))
Run Code Online (Sandbox Code Playgroud)

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


Jos*_*lor 5

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

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