Common Lisp - flatting a list that may contain symbols

后端 未结 1 411
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-26 06:54

This is #7 of of 99 Lisp problems: transform a list, possibly holding lists as elements into a `flat\' list by replacing each list with its elements (recursively). I have tried

1条回答
  •  一向
    一向 (楼主)
    2021-01-26 07:52

    Quoted elements in a list? That usually does not make sense. Why would you have it quoted?

    (a b c) is a list of three symbols. Why would you quote elements in the list? like in (a 'b c)? Why? What would be the purpose of the quote?

    In Common Lisp ' is a readmacro which expands 'a into (QUOTE A). Since this is a normal list, a typical flatten operation will collect the symbols QUOTE and A into the flat list. This is because a flatten function typicall checks whether something is an atom or not. If you don't want this, your flatten function needs to check if something is an atom or a two-element list with QUOTE as its first symbol.

    But as I said above, the default usage is just to flatten symbols, since quoted symbols are usually not useful inside a list. You need to extend the flatten function otherwise.

    For example:

    (defun flatten (l &key (test #'atom))
      (cond ((null l) nil)
            ((funcall test l) (list l))
            (t (loop for a in l nconc (flatten a :test test)))))
    
    
    CL-USER > (flatten '(a (('b) c) ('d) )
                       :test (lambda (item)
                               (or (atom item)
                                   (and (eq (first item) 'quote)
                                        (null (cddr item))))))
    
    (A (QUOTE B) C (QUOTE D))
    

    0 讨论(0)
提交回复
热议问题