s1m*_*nw1 4 sequences clojure lazy-evaluation lazy-sequences kotlin
Clojure提供了对(无限)序列中的值进行惰性求值的方法.这样,只有在实际消耗时才会计算值.
一个重复元素的无限序列的示例:
(take 3 (repeat "Hello StackOverflow"))
//=> ("Hello StackOverflow" "Hello StackOverflow" "Hello StackOverflow")
Run Code Online (Sandbox Code Playgroud)
使用take
帮助只消耗我们想要的序列中的任意数量的元素.没有它,一个人OutOfMemoryError
会迅速杀死这个过程.
无限序列的另一个例子如下:
(take 5 (iterate inc 1))
//(1 2 3 4 5)
Run Code Online (Sandbox Code Playgroud)
或者是提供阶乘函数的更高级序列:
((defn factorial [n]
(apply * (take n (iterate inc 1)))) 5)
Run Code Online (Sandbox Code Playgroud)
Kotlin是否提供类似的序列?他们看起来怎么样?
我自己回答了这个问题,以便记录这里的知识.这很好根据我可以回答我自己的问题吗?
在Kotlin中,我们也可以使用Sequences来进行延迟评估.为了创建一个序列,我们可以使用generateSequence
(有或没有提供seed
.
Run Code Online (Sandbox Code Playgroud)fun <T : Any> generateSequence( seed: T?, nextFunction: (T) -> T? ): Sequence<T> (source)
返回由起始值
seed
和函数定义的序列nextFunction
,调用该序列以在每次迭代时基于前一个值计算下一个值.
以下将显示比较Clojure与Kotlin序列的一些实例.
take
的无限序列的一个静态值Clojure的
(take 3 (repeat "Hello StackOverflow"))
Run Code Online (Sandbox Code Playgroud)
科特林
generateSequence { "Hello StackOverflow" }.take(3).toList()
Run Code Online (Sandbox Code Playgroud)
这些非常相似.在Clojure中我们可以使用repeat
和在Kotlin中它只是generateSequence
一个静态值,将永远屈服.在这两种情况下,take
都用于定义我们想要计算的元素数量.
注意:在Kotlin中,我们将结果序列转换为带有的列表 toList()
take
来自动态值的无限序列的简单Clojure的
(take 5 (iterate inc 1))
Run Code Online (Sandbox Code Playgroud)
科特林
generateSequence(1) { it.inc() }.take(5).toList()
Run Code Online (Sandbox Code Playgroud)
这个例子有点不同,因为序列无限地产生前一个值的增量.generateSequence
可以使用种子(此处为:) 1
和nextFunction
(增加之前的值)来调用Kotlin .
Clojure的
(take 5 (drop 2 (cycle [:first :second :third ])))
// (:third :first :second :third :first)
Run Code Online (Sandbox Code Playgroud)
科特林
listOf("first", "second", "third").let { elements ->
generateSequence(0) {
(it + 1) % elements.size
}.map(elements::get)
}.drop(2).take(5).toList()
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我们循环地重复列表的值,删除前两个元素然后取5.它在Kotlin中恰好相当冗长,因为列表中的重复元素并不简单.为了解决这个问题,一个简单的扩展函数使相关代码更具可读性:
fun <T> List<T>.cyclicSequence() = generateSequence(0) {
(it + 1) % this.size
}.map(::get)
listOf("first", "second", "third").cyclicSequence().drop(2).take(5).toList()
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要的,让我们看看如何用Kotlin序列解决因子问题.首先,让我们回顾一下Clojure版本:
Clojure的
(defn factorial [n]
(apply * (take n (iterate inc 1))))
Run Code Online (Sandbox Code Playgroud)
我们从序列中取n个值,得到一个从1开始的递增数,并在...的帮助下累加它们apply
.
科特林
fun factorial(n: Int) = generateSequence(1) { it.inc() }.take(n).fold(1) { v1, v2 ->
v1 * v2
}
Run Code Online (Sandbox Code Playgroud)
Kotlin提供fold
让我们轻松积累价值的东西.
归档时间: |
|
查看次数: |
380 次 |
最近记录: |