您的解决方案不完整,因为可能有一个或多个声明。
虽然您可以为此使用一些现成的功能,但它有助于对在类似情况下有用的技术进行很好的研究。
如果你有表格列表
(alpha beta x epsilon ... omega)
其中 x 是您想要拆分列表的感兴趣项目,您可以使用 member 函数查找以 x 开头的子列表,然后使用 ldiff 函数获取该子列表的前缀列出(alpha beta),其中不包括(x epsilon omega)。第一步:
(member-if-not (lambda (x) (eq x 'declare)) '(declare declare 3 4 5))
-> (3 4 5)
当然,我们正在寻找(declare ...) 而不是declare。我们不能为此使用:key #'car,因为表单可能不是 conses,所以:
(member-if-not (lambda (x) (and (consp x) (eq (car x) 'declare)))
'((declare foo) (declare bar) 3 4 5))
-> (3 4 5)
现在如何自己获取声明和剩余表单:
(defun separate-decls-and-body (body)
(let* ((just-the-code (member-if-not (lambda (x)
(and (consp x) (eq (car x) 'declare)))
body))
(just-the-decls (ldiff body just-the-code)))
(values just-the-decls just-the-code)))
测试:
> (separate-decls-and-body '((declare (optimize (speed 3))) (declare (type)) 1 2 3))
((DECLARE (OPTIMIZE (SPEED 3))) (DECLARE (TYPE))) ;
(1 2 3)
> (separate-decls-and-body '((declare (optimize (speed 3)))))
((DECLARE (OPTIMIZE (SPEED 3)))) ;
NIL
> (separate-decls-and-body '())
NIL ;
NIL
> (separate-decls-and-body '(1 2 3))
NIL ;
(1 2 3)
member 家人和ldiff 是您的朋友。 ldiff 基于 member 返回原始列表的子结构而不是副本这一事实;它只是沿着列表前进以寻找该指针,并将所有先前的项目作为新列表返回。