use*_*949 4 lisp clisp common-lisp
我有一个lisp作业,我很难用它.
我必须编写一个执行联合操作的函数.该函数采用2个输入,以原子或列表的形式和每个元素的联合,保留顺序并剥离所有级别的括号.
功能的输出:
(my-union 'a 'b)                         ;; (a b)
(my-union 'a '(b))                       ;; (a b)
(my-union '(a b) '(b c))                 ;; (a b c)
(my-union '(((a))) '(b(c((d e))a)))      ;; (a b c d e)
我对lisp很新.这是我到目前为止所写的内容,它仅适用于第三个示例:
(defun new-union (a b)
 (if (not b)
      a
      (if (member (car b) a)
        (new-union a (cdr b))
        (new-union (append a (list (car b))) (cdr b)))))
任何帮助,将不胜感激!
由于这是你的第一个家庭作业,而且你是Lisp的新手,这里有一个非常简单的自上而下的方法,不用担心性能,并且充分利用CL提供的工具:
在Common Lisp中,已经有一个删除重复项的函数:remove-duplicates.将它与:from-endkeyword-argument一起使用将"保留顺序".现在,假设你有一个函数flatten,它可以平滑任意嵌套列表.然后问题的解决方案是:
(defun new-union (list1 list2)
  (remove-duplicates (flatten (list list1 list2)) :from-end t))
这是我在没有给出进一步限制的情况下解决问题的方法,并且没有理由担心性能问题.尽可能多地使用当前工具箱,除非必要,否则不要重新发明轮子.
如果你像这样处理问题,那就归结为编写flatten函数,我将把它作为练习留给你.这不是太难,一个简单的选择是写一个递归函数,接近这样的问题:
如果要展平的列表的第一个元素本身是一个列表,则将展平的第一个元素追加到展平的休息符.如果第一个元素不是列表,只需将其添加到列表的展平其余部分.如果输入根本不是列表,则返回它.
这应该是一个很好的练习,只需几行代码就可以完成.
(如果你想要非常正确,使用辅助函数来完成工作并检查包装函数是否参数确实是一个列表.否则,flatten也将对原子起作用,这对你来说可能是也可能不是问题.)
现在,假设你写了flatten:
> (defun new-union (list1 list2)
    (remove-duplicates (flatten (list list1 list2)) :from-end t))
NEW-UNION
> (new-union 'a 'b)
(A B)
> (new-union 'a '(b))
(A B)
> (new-union '(a b) '(b c))
(A B C)
> (new-union '(((a))) '(b (c ((d e)) a)))
(A B C D E)