Racket for/list是否做了不必要的反转?
我第一次拨动宏步进器,注意到一个Racket for/list是否做了不必要的反转?,racket,list-comprehension,reverse,for-comprehension,cons,Racket,List Comprehension,Reverse,For Comprehension,Cons,我第一次拨动宏步进器,注意到一个for/list扩展成了一个名为alt reverse的代码。for/list是否会将每个项目压缩到空列表的前面,然后将其反转?这似乎效率很低 我写了一个小测试: (define (test n) (time (for/list ([x (in-range n)]) (list x x))) (time (for/fold ([result '()]) ([x (in-range n)])
for/list
扩展成了一个名为alt reverse
的代码。for/list
是否会将每个项目压缩到空列表的前面,然后将其反转?这似乎效率很低
我写了一个小测试:
(define (test n)
(time
(for/list ([x (in-range n)])
(list x x)))
(time
(for/fold ([result '()])
([x (in-range n)])
(cons (list x x) result)))
(void))
事实上,for/list
版本运行时间约为for/fold
的150%,而没有reverse
,这种差异显然完全是由于额外的垃圾收集:
> (test 500000)
cpu time: 1059 real time: 2079 gc time: 940
cpu time: 614 real time: 1231 gc time: 550
> (test 500000)
cpu time: 1060 real time: 3889 gc time: 907
cpu time: 770 real time: 1363 gc time: 699
> (test 500000)
cpu time: 1035 real time: 2479 gc time: 917
cpu time: 736 real time: 2535 gc time: 651
听起来我不应该养成为/list打电话的习惯。是否有更有效的方法以“正向”顺序创建列表(即,最后评估的项是列表中的最后一项)?查看Git历史记录,我发现对/list进行
避免反向的更改是,但由于与连续性的微妙互动,可能会触发四元时间行为。(我确实想知道,即将推出的Chez方案后端是否意味着“当Racket有朝一日能够更好地实现延续性”可能很快就会到来。)
您可以按照“向前”的顺序构建列表,正如第一条提交消息所说,“cons
ing on a recursive call.”《球拍指南》部分详细讨论了map
-风格和for/fold
-风格方法之间的权衡
另外,作为将来的参考,Racket社区倾向于更多地生活在非常活跃和友好的渠道上,并且在某种程度上是在Stack Overflow上。使用for/fold
的版本与使用for/list
的版本不一样,因为它根本不使用result
。@AlexisKing噢!谢谢我刚修好。现在用新结果更新问题…