В Kotlin мы также можем использовать ленивую оценку, используя Последовательности тоже. Чтобы создать последовательность, мы можем использовать generateSequence
< / a> (с предоставлением seed
.
fun <T : Any> generateSequence(
seed: T?,
nextFunction: (T) -> T?
): Sequence<T> (source)
Возвращает последовательность, определяемую начальным значением seed
и функцией nextFunction
, которая вызывается для вычисления следующего значения на основе предыдущего на каждой итерации.
Ниже будут показаны некоторые примеры сравнения последовательностей Clojure и Kotlin.
1. Простой take
из бесконечной последовательности одного статического значения
Clojure
(take 3 (repeat "Hello StackOverflow"))
Котлин
generateSequence { "Hello StackOverflow" }.take(3).toList()
Они очень похожи. В Clojure мы можем использовать repeat
, а в Kotlin просто generateSequence
со статическим значением, которое будет возвращаться вечно. В обоих случаях take
используется для определения количества элементов, которые мы хотим вычислить.
Примечание: в Kotlin мы преобразуем полученную последовательность в список с toList()
2. Простой take
из бесконечной последовательности динамического значения
Clojure
(take 5 (iterate inc 1))
Котлин
generateSequence(1) { it.inc() }.take(5).toList()
Этот пример немного отличается, потому что последовательности дают бесконечное приращение предыдущего значения. Kotlin generateSequence
может быть вызван с начальным значением (здесь: 1
) и nextFunction
(увеличивая предыдущее значение).
3. Циклическое повторение значений из списка.
Clojure
(take 5 (drop 2 (cycle [:first :second :third ])))
// (:third :first :second :third :first)
Котлин
listOf("first", "second", "third").let { elements ->
generateSequence(0) {
(it + 1) % elements.size
}.map(elements::get)
}.drop(2).take(5).toList()
В этом примере мы циклически повторяем значения списка, отбрасываем первые два элемента, а затем берем 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()
4. Факториал
И последнее, но не менее важное: давайте посмотрим, как факторная проблема может быть решена с помощью последовательности Kotlin. Сначала рассмотрим версию Clojure:
Clojure
(defn factorial [n]
(apply * (take n (iterate inc 1))))
Мы берем n значений из последовательности, которая дает возрастающее число, начиная с 1, и накапливаем их с помощью apply
< / а>.
Котлин
fun factorial(n: Int) = generateSequence(1) { it.inc() }.take(n).fold(1) { v1, v2 ->
v1 * v2
}
Kotlin предлагает fold
, который позволяет нам легко накапливать значения .
person
s1m0nw1
schedule
07.06.2018