首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Lisp函数说明

Lisp函数说明
EN

Stack Overflow用户
提问于 2013-12-06 05:08:23
回答 3查看 152关注 0票数 1

我有一个用LISP编写的示例,它从列表的每个级别中删除一个给定的数字:

代码语言:javascript
复制
(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)

如果我有行没有list和append ((t(mapcar #'(lambda (l) (remove_aux e l)) l))),结果是((1) NIL (3) ((NIL (3) NIL) (4)))),如果它有append,但没有list ( (t(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))) ),那么结果是(1 3 3 4),我不知道为什么,因为我在Common Lisp控制台中执行了(apply 'append '((1) NIL (3) ((NIL (3) NIL) (4))))),结果是((1 3 (NIL (3) NIL) (4))),所以我真的很困惑。有人能一步一步地向我解释这一切是如何工作的吗?

EN

回答 3

Stack Overflow用户

发布于 2013-12-06 05:28:41

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

代码语言:javascript
复制
(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)
  )
)
票数 1
EN

Stack Overflow用户

发布于 2013-12-06 07:59:19

代码语言:javascript
复制
;; 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的参数,它再次将元素连接到一个列表中。当连接列表时,要删除的元素是一个空列表,在连接过程中它实际上被忽略了。

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

票数 1
EN

Stack Overflow用户

发布于 2013-12-09 01:04:30

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

代码语言:javascript
复制
(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.

你问题中的过程有一些不必要的杂乱无章的部分,比如追加、映射等。

如果您在下面重新注释,我将解释算法。

祝你一路顺风。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20410743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档