Lisp 删除每个子列表的第一个元素

Lisp 删除每个子列表的第一个元素,lisp,common-lisp,Lisp,Common Lisp,我应该写一个函数来删除每个子列表的第一个元素 所以如果给我们(1(2(34)5)6),我的函数应该返回(((4)5)6) 这是我尝试过的,但它又回来了 ((34)5)6) (3个不应该在那里) 有什么想法吗?你的代码 您的podlista函数有4个子句,最后一个子句不可访问。这是因为每个Lisp对象要么是an要么是a,对于acons,都将返回t 下一个问题是第三个子句是非递归的(必须删除cdr中的第一个元素) 但是,您的代码有一个更大的问题。 当函数看到cons时,它必须知道是否要删除第一个元素

我应该写一个函数来删除每个子列表的第一个元素

所以如果给我们(1(2(34)5)6),我的函数应该返回(((4)5)6)

这是我尝试过的,但它又回来了 ((34)5)6)

(3个不应该在那里)

有什么想法吗?

你的代码 您的
podlista
函数有4个子句,最后一个子句不可访问。这是因为每个Lisp对象要么是an要么是a,对于a
cons
,都将返回
t

下一个问题是第三个子句是非递归的(必须删除
cdr
中的第一个元素)

但是,您的代码有一个更大的问题。 当函数看到
cons
时,它必须知道是否要删除第一个元素。瞧,它一定是

  • 使用循环(或映射)以非递归方式处理列表,或者
  • 使用第二个参数指定列表中的第一个/非第一个位置
解决方案1-循环/映射 假设你被允许 使用,解决方案是

(defun drop-first (l)
  (if (consp l)
      (mapcar #'drop-first (rest l))
      l))
(drop-first '(1 ((7 8) 9) (2 (3 4) 5) 6))
==> ((9) ((4) 5) 6)
(drop-first '(1 (2 (3 4) 5) 6))
==> (((4) 5) 6)
mapcar
当然是递归地定义为

(defun mapcar (f l) 
  (and l 
       (cons (funcall f (first l))
             (mapcar f (rest l)))))
解决方案2-额外参数 测验
如果你使用标准的缩进和排列,那就太好了。英文函数名也不会有什么坏处。请注意,有些简单的情况下,您的代码无法正常工作,例如
(12)
,它返回
NIL
,而不是预期的
(2)
。我很想了解我的代码有什么问题,我从未使用过mapcar,也不知道它会做什么。
(defun mapcar (f l) 
  (and l 
       (cons (funcall f (first l))
             (mapcar f (rest l)))))
(defun first-drop (l &optional (top-level t)) 
  (cond ((atom l) l)
        (t
         (when top-level        ; drop first list element
           (pop l))
         ;; collect all the list element
         (cons (first-drop (car l) t) ; drop first in the CAR
               (first-drop (cdr l) nil))))) ; do NOT drop first in the rest of the list
(defparameter *test-cases*      ; list of (ARG RET)
  '(((1 2 3) (2 3))
    ((1 (2 (3 4) 5) 6) (((4) 5) 6))
    ((1 (3 (5 6) 4) (7 8 9) 2) (((6) 4) (8 9) 2))))
(loop :for (arg ret) :in *test-cases* :do
  (assert (equal (drop-first arg) ret))
  (assert (equal (first-drop arg) ret)))