如何解决在 Lisp 中的 mapcon 上应用附加
Lisp 函数 G
定义为:
(defun g (l)
(mapcon #'list l))
对表单 (apply #'append (mapcon #'g '(1 2)))
求值的结果是什么?
证明答案是正确的。
我已经看到 mapcon
与 nconc
和 cdr
一起使用,但最终答案将是 (1 2 2 2)
,我不知道如何正确解释它。请帮忙。
解决方法
首先,让我们调用:
(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
这意味着如果 l1
、l2
和 l3
是列表,则包含它们所有元素的列表是:
(append l1 l2 l3)
此处 append
的参数存储在列表中,因此将任意参数列表传递给函数的方法是使用 apply
。所以这意味着 (apply #'append lists)
连接列表中的所有列表,这就是为什么在您的情况下结果是 (1 2 2 2)
。
请注意,当参数数量是任意的(可能很大)时,不建议使用 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 )
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。