【问题标题】:Lisp function explanationLisp 函数说明
【发布时间】:2013-12-23 00:39:57
【问题描述】:

我在 LISP 中有这个例子,它从列表的每一层中删除一个给定的数字:

(defun remove_aux (e l)
 (cond 
  ((equal e l) nil)
  ((atom l) (list l))
  (t(list(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))))))

 (defun remove_el (e l)
  (car (remove_aux e l)))

所以,如果它像这样运行:(remove_el 2 '(1 2 3 ((2 3 2) 4))) => (1 3 ((3) 4))

我不太明白这条线是如何工作的:(t(list(apply 'append (mapcar #'(lambda (l) (sterge_aux e l)) l))))

如果我有没有列表的行并附加((t(mapcar #'(lambda (l) (remove_aux e l)) l))),结果是((1) NIL (3) ((NIL (3) NIL) (4)))) 如果它有附加但没有列出( (t(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))) ),那么结果是(1 3 3 4),我不明白为什么,因为我做了@987654327 @ 在 Common Lisp 控制台中,结果是 ((1 3 (NIL (3) NIL) (4))) 所以我真的很困惑。有人可以逐步向我解释这一切是如何工作的吗?

【问题讨论】:

  • 这看起来很难看。可以格式化一下代码吗?

标签: lisp common-lisp


【解决方案1】:

实现您想要实现的过程基本上类似于以下过程:

(defun remove-all (e l)"Removes all occurrences of e from a list l."
  (cond
   ((null l) '())
   ((equal e (car l)) (remove-all e (cdr l)))    
   ((not (atom (car l)))
    (cons (remove-all e (car l))
          (remove-all e (cdr l))))
   (t (cons (car l)
            (remove-all e (cdr l))))))
;note: the e is not neccessarily an atom, the l is not necessarily a list of atoms.

您问题中的程序包含不必要的混乱部分,例如附加、地图等。

如果你在下面提出建议,我会解释算法。

有一个不错的 hack。

【讨论】:

    【解决方案2】:
    ;; append elements of each list in argument together
    (append '(a) '(b) '(c d) '(e))             ; ==> (a b c d e)
    
    ;; append elements of each sublist in argument
    (apply #'append '((a) (b) (c d) (e)))      ; ==> (a b c d e)
    
    ;; apply function on each element of list into new list
    (mapcar #'(lambda (x) (+ x 1)) '(1 3 5 6)) ; ==> (2 4 6 7)
    

    那么默认情况在你的函数中做了什么.. 它适用于 lst 的每个子列表并将其包装在一个列表中,所以如果 l'(a y 2 z) 并且 e2,那么mapcar 的结果是 '((a) (y) () (z)),然后是 apply-append 的参数,它将元素再次连接到一个列表中。连接列表时,要删除的元素是一个空列表,在连接过程中实际上会被忽略。

    由于您在帮助程序中创建了所有附加列表,您可以将apply-append 替换为(mapcan #'(lambda (l) (remove_aux e l)) l)。更明显的方法是使用reduce,而更有效的方法可能是使用loop

    【讨论】:

      【解决方案3】:

      我已经对下面的代码进行了注释,希望能解释发生了什么。您可能会感到困惑,因为 l 在 lambda 中被重新定义......所以 t 行(在您的示例中)上面有 2 个“l”,但第一个与第二个不同。

      (defun remove_aux (e l)
       (cond 
        ((equal e l) nil) ;if e equals l return nil
        ((atom l) (list l)) ;if l is an atom return a list with just l in it
        (t   ; otherwise...
          (list ;create a list
            (apply 'append ; whose contents are created by appending
                           ; together the lists that come out of this mapcar
                           ; (apply the append method)
              (mapcar #'(lambda (l) ( ; iterate over each of the elements in list l
                                      ; the one after the lambda not the one 
                                      ; being passed to the lambda. 
                                      ; (this is a horrible name choice
                                      ; lambda(l-item) would be much better)
                                      remove_aux e l
                                      ; recursively call this method 
                                      ; with e (which was passed in at the start)
                                      ; and l which isn't the l passed in,
                                      ; but is an entry of it (see why naming's 
                                      ; so important?)
                                      ; this returns a list
                                      ; which will get appended by the append 
                                      ; with the results of all the other calls 
                                      ; to remove_aux for each item in the outer l
                                      )
                        ) l)
            )))))
      
        (defun remove_el (e l)
          (car (remove_aux e l)
        )
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-10
        • 2017-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-09
        • 2021-08-13
        • 1970-01-01
        相关资源
        最近更新 更多