Я экспериментирую с последовательностями Kotlin и, в частности, более сложными, которые не являются простыми вычислениями по предыдущему значению.Рекурсивное определение бесконечной последовательности в Котлине
Одним из примеров, которые я хотел бы определить, является последовательность всех простых чисел.
Простым способом определения следующего простого является следующее целое число, которое не делится ни на один из предыдущих простых чисел в последовательности.
В Scala это можно перевести:
def primeStream(s: Stream[Int]): Stream[Int] = s.head #:: primeStream(s.tail filter(_ % s.head != 0))
val primes = primeStream(Stream.from(2))
// first 20 primes
primes.take(20).toList
У меня возникли проблемы перевод это Котлин. В scala это работает, потому что вы можете передать функцию, которая возвращает последовательность, которая будет лениво оценена, но я не могу сделать то же самое в Котлине.
В Котлин я попытался
fun primes(seq: Sequence<Int>):Sequence<Int> = sequenceOf(seq.first()) + primes(seq.drop(1).filter {it % seq.first() != 0})
val primes = primes(sequence(2) {it + 1})
primes.take(20).toList()
Но это, очевидно, не работает, потому что функция вычисляется сразу и приводит к бесконечной рекурсии.
Ницца. Интересно, почему ['Sequence .plus (Sequence )'] (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/kotlin.-sequence/plus.html) не ленив, как вы реализовали 'lazyPlus' ... –
mfulton26
Ну,' Sequence .plus (...) 'просто недостаточно ленив. :) Элементы результата 'Sequence ' оцениваются лениво, но объект 'Sequence ' в правом операнде оценивается с нетерпением, чего нам следует избегать здесь, так как это приведет к 'StackOverflowError'. –
hotkey
Это замечательно как общая функция библиотеки. Он работает быстро для меня. Можете ли вы объяснить необходимость преобразования последовательности в итератор и обратно в реализации primesFilter? Кажется, что это немного, но если вы этого не сделаете, я думаю, что ленивая оценка не работает. Есть ли возможность не требовать этого? –