您需要提前检查或子列表,例如 '((or ...) ...),以便您可以将其转换为 '(... ...)。
它的条件很简单:
(and (listp lst) (listp (first lst))
(eq (first (first lst)) 'or))
还有变压器:
(append (remove-or (rest (first lst)))
(remove-or (rest lst)))
因此,这将我们带到了您的函数,其中第三个条件分支略有修改:
(defun remove-or (lst)
(cond ((null lst) lst)
((atom lst) lst)
((and (listp lst) (listp (first lst))
(eq (first (first lst)) 'or))
(append (remove-or (rest (first lst)))
(remove-or (rest lst))))
(t (cons (remove-or (first lst))
(remove-or (rest lst))))))
但是这个函数不会处理一种特殊情况:列表最开始的 or :(OR ab(或(或 cd)e))。但是有一个额外的条件分支,像((and (listp x) (eq (first x) 'or)) (remove-or (cdr x)))
我们将删除or
的 s 也像变量一样:(ab或c或)。
所以这种情况必须分开处理,例如:
(defun remove-or-head (lst)
(remove-or (if (and (listp lst) (eq (first lst) 'or))
(rest lst)
lst))
将它们与隐藏的递归函数放在一起:
(defun remove-or (lst)
(labels ((remove-or-rec (lst)
(cond ((null lst) lst)
((atom lst) lst)
((and (listp lst) (listp (first lst))
(eq (first (first lst)) 'or))
(append (remove-or-rec (rest (first lst)))
(remove-or-rec (rest lst))))
(t (cons (remove-or-rec (first lst))
(remove-or-rec (rest lst)))))))
(remove-or-rec (if (and (listp lst) (eq 'or (first lst)))
(rest lst)
lst))))