mik*_*era 11 macros loops clojure
我经常发现自己想要使用整数索引(如"dotimes")多次有效地运行Clojure函数,但也将结果作为现成的序列/列表(如"for")得到.
即我想做这样的事情:
(fortimes [i 10] (* i i))
=> (0 1 4 9 16 25 36 49 64 81)
Run Code Online (Sandbox Code Playgroud)
显然,有可能做到:
(for [i (range 10)] (* i i))
Run Code Online (Sandbox Code Playgroud)
但是,如果可能的话,我想避免创建和丢弃临时范围列表.
在Clojure中实现这一目标的最佳方法是什么?
正如您在第二个示例中所示,在for循环中生成范围是在Clojure中解决此问题的惯用解决方案.
由于Clojure以功能范例为基础,因此默认情况下在Clojure中编程将生成这样的临时数据结构.但是,由于"range"和"for"命令都使用惰性序列,因此编写此代码不会强制整个临时范围数据结构立即存在于内存中.如果使用得当,则本例中使用的延迟seq的内存开销非常低.此外,您的示例的计算开销是适度的,并且应该只与范围的大小线性增长.对于典型的Clojure代码,这被认为是可接受的开销.
完全避免这种开销的适当方法,如果临时范围列表对于您的情况绝对是不可接受的,那就是使用原子或瞬态编写代码:http://clojure.org/transients.但是,如果你这样做,你将放弃Clojure编程模型的许多优点,以换取更好的性能.
小智 5
我编写了一个迭代宏,可以非常有效地执行此操作和其他类型的迭代.该包在github和clojars上都被称为clj-iterate.例如:
user> (iter {for i from 0 to 10} {collect (* i i)})
(0 1 4 9 16 25 36 49 64 81 100)
Run Code Online (Sandbox Code Playgroud)
这不会创建临时列表.