【问题标题】:Applying append on mapcon in Lisp在 Lisp 中的 mapcon 上应用附加
【发布时间】:2021-04-11 17:52:24
【问题描述】:

Lisp 函数G 定义为:

(defun g (l)
   (mapcon #'list l)) 

评估表单(apply #'append (mapcon #'g '(1 2))) 的结果是什么?
证明答案。

我看到mapconnconccdr 一起使用,但最终答案将是(1 2 2 2),我不知道如何正确解释它。请帮忙。

【问题讨论】:

    标签: functional-programming lisp common-lisp map-function


    【解决方案1】:

    首先,让我们调用:

    (mapcon (lambda (list) (print list) nil) '(1 2))
    

    因为匿名函数一直返回NIL,所以结果列表是NIL;调用会打印:

    (1 2) 
    (2) 
    

    因此,在您的示例中,当您调用 (mapcon #'g '(1 2)) 时,g 将首先使用 (1 2) 调用,然后使用 (2)。函数g 返回一个列表,mapcon 将它们连接起来。

    通过显式计算每个部分,可以在 REPL 中复制所发生的事情:

    USER> (mapcon #'list '(1 2))
    ((1 2) (2))
    
    USER> (mapcon #'list '(2))
    ((2))
    
    USER> (nconc ** *)
    ((1 2) (2) (2))
    

    最后,(apply #'append list-of-lists) 使用参数列表调用 append

    append的签名是:

    append &rest lists => result 
    

    这意味着如果l1l2l3是列表,则包含它们所有元素的列表是:

    (append l1 l2 l3)
    

    这里append 的参数存储在一个列表中,因此将任意参数列表传递给函数的方法是使用apply。所以这意味着(apply #'append lists) 连接列表中的所有列表,这就是为什么在你的情况下结果是(1 2 2 2)

    请注意,当参数的数量是任意的(可能很大)时,不建议使用apply,因为applyCALL-ARGUMENTS-LIMIT 的限制。另一种可能的方法是:

    (loop for list in lists append list)
    

    【讨论】:

      【解决方案2】:

      这里要理解的主要是

      (mapcon #'f xs)  =  (apply #'nconc  (maplist #'f xs))
                       =  (loop  for ys on xs  nconc (f ys))
      

      这样

      (g xs)              =
      (mapcon #'list xs)  =  (apply #'nconc  (maplist #'list xs))
                          =  (loop  for ys on xs  nconc   (list ys))
                          =  (loop  for ys on xs  append  (list ys))
                          =  (loop  for ys on xs  collect       ys )
                      ;;  =  (maplist  #'identity  xs)
      

      这只是 #'cdr 对参数列表的迭代应用,收集其非空后缀:

      [4]> (loop  for ys on '(1 2)  collect ys)    ; (g '(1 2))
      ((1 2) (2))
      
      [5]> (loop  for ys on '(  2)  collect ys)    ; (g '(  2))
      (      (2))
      

      所以我们有

      (mapcon #'g '(1 2)) 
      =
      (loop  for ys on '(1 2)  nconc (g ys))
      =
      (loop  for ys in '((1 2) (2))  nconc (g ys))     ; ----- 'in' NB
      =
      (nconc  (g '(1 2))  (g '(2)))
      =
      (append  '((1 2) (2))  '((2)))
      =
      '(         (1 2) (2)     (2) )
      

      因此

      (apply #'append (mapcon #'g '(1 2)))
      =
      (apply #'append (nconc (g '(1 2)) (g '(2))))
      =
      (apply #'append (append '((1 2) (2)) '((2))))
      =
      (apply #'append '(        (1 2) (2)    (2) ))
      =
      (        append          '(1 2)'(2)   '(2)  )
      =
      '(                         1 2   2      2   )
      

      【讨论】:

        猜你喜欢
        • 2017-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-11
        • 1970-01-01
        • 2012-01-20
        • 1970-01-01
        相关资源
        最近更新 更多