Functional programming 在Lisp中对mapcon应用append

Functional programming 在Lisp中对mapcon应用append,functional-programming,lisp,common-lisp,map-function,Functional Programming,Lisp,Common Lisp,Map Function,Lisp函数G的定义如下: (defun g (l) (mapcon #'list l)) 计算表单(apply#'append(mapcon#'g'(12))的结果是什么 证明答案的正确性 我已经看到mapcon与ncoc和cdr一起工作,但最终的答案将是(12),我不知道如何正确解释它。请帮忙。首先,我们打电话: (mapcon (lambda (list) (print list) nil) '(1 2)) 由于匿名函数始终返回NIL,因此结果列表为NIL;调用打印以下内容:

Lisp函数
G
的定义如下:

(defun g (l)
   (mapcon #'list l)) 
计算表单
(apply#'append(mapcon#'g'(12))
的结果是什么
证明答案的正确性

我已经看到
mapcon
ncoc
cdr
一起工作,但最终的答案将是
(12)
,我不知道如何正确解释它。请帮忙。

首先,我们打电话:

(mapcon (lambda (list) (print list) nil) '(1 2))
由于匿名函数始终返回NIL,因此结果列表为NIL;调用打印以下内容:

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

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

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

USER> (mapcon #'list '(2))
((2))

USER> (nconc ** *)
((1 2) (2) (2))
最后,
(应用#'附加列表)
调用带有参数列表的
附加

append
的签名为:

append &rest lists => result 
这意味着如果
l1
l2
l3
是列表,则包含其所有元素的列表是:

(append l1 l2 l3)
这里,
append
的参数存储在一个列表中,因此将任意参数列表传递给函数的方法是使用
apply
。这意味着
(apply#'append list)
连接列表中的所有列表,这就是为什么在您的例子中结果是
(12)

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

(loop for list in lists append list)

这里要理解的主要事情是

(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   )