`mapcan`真的用`nconc`吗?

问题描述 投票:0回答:2

根据 Common Lisp HyperSpec (CLHS)

mapcan
使用
nconc
将其结果组合成一个列表。 CLHS 也这么说

(mapcon f x1 ... xn)
   ==  (apply #'nconc (maplist f x1 ... xn))

所以我一直担心在

apply
很低的情况下使用
call-arguments-limit
的后果 - CLHS 说它可以低至 50,而在 LispWorks 上它是 2047。在 LispWorks 上,

(mapcan #'list (loop for i from 0 to call-arguments-limit collect i))

成功,而

(apply #'nconc (mapcar #'list (loop for i from 0 to call-arguments-limit collect i)))

失败。如果

mapcan
真的必须使用
nconc
,这两个不应该都失败吗?

lisp common-lisp
2个回答
4
投票

规范的一个重点是1.4.3 部分不是本标准的正式部分,其中特别指出示例仅供说明使用,不是标准的一部分。

通常在 HyperSpec 中,展示如何用另一个构造表达一个构造的示例旨在展示函数的意图,并且可以假设该示例适用于一些没有物理限制(如内存等)的抽象实现

没有requirement

MAPCAN
MAPCON
以此处显示的确切方式使用
NCONC
,事实上我认为没有
==
的正式定义(技术上代码也使用省略号,因此它不是用 Common Lisp 编写的)。

一个更好的例子是使用

REDUCE
NCONC
连续的结果,甚至是
LOOP
。我认为在这个例子中使用
APPLY
是不幸的,但最终你可以假设
MAPCON
MAPCAN
都不受
CALL-ARGUMENTS-LIMIT
的限制。

例如,你可以这样表达,但实际的

MAPCAN
可能不需要像
MAPCAR
那样分配中间列表,它可以只是融合两个操作:

(reduce #'nconc (mapcar f x1 .. xn))

0
投票

引用自标准:

mapcan
mapcon
分别像
mapcar
maplist
,不同之处在于应用函数的结果通过使用
nconc
而不是
list
组合成一个列表。

那么,是否意味着

mapcar
必须由
(apply #'list ...)
执行?别傻了,当然没必要。这意味着
mapcar
调用的函数的结果以与
list
相同的方式组合成一个列表
:通过构建cons单元链,其汽车指向返回值。

完全相同的方式,

mapcan
调用的函数返回的结果按照
nconc
的方式组合,即它们必须是列表并且这些列表被破坏性地连接起来。

这就是标准中语言的意思。

© www.soinside.com 2019 - 2024. All rights reserved.