首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >支持重复迭代的素数序列

支持重复迭代的素数序列
EN

Code Review用户
提问于 2020-12-20 04:26:05
回答 1查看 70关注 0票数 3

我是一个长期的Java程序员,但最近我决定给Kotlin一次尝试。到目前为止,我喜欢语言的特点,感觉比我习惯的更有表现力。作为实践,我编写了这个函数,它生成一个可重复的素数序列(即,该序列可以被多次迭代,并将利用过去迭代的结果来加快未来的迭代)。对我来说,这感觉很稳固,但是我想知道在科特林的老将那里会是什么样子--我有没有充分利用语言的特点,或者我应该遵循的惯例?

我有一个特别的问题是关于顶级函数与子类的问题;这里我选择实现一个返回一个primeSequence(): Sequence<Long>的顶级函数object,但是我可以很容易地实现一个类PrimeSequence : Sequence<Long>。在什么时候使用其中一种或另一种是否有很好的经验法则?

代码语言:javascript
复制
fun primeSequence(): Sequence<Long> = object: Sequence<Long> {
    private val knownPrimes: MutableList<Long> = arrayListOf(2L, 3L)

    private fun Long.isMultipleOf(n: Long) = (this%n == 0L)
    
    private fun Long.isPrime() = knownPrimes
            .takeWhile { it*it <= this }
            .none { this.isMultipleOf(it) }

    override fun iterator(): Iterator<Long> = object: Iterator<Long> {
        private var lastPrime: Long? = null

        override fun hasNext() = true

        override fun next(): Long {
            val nextPrime = when(val lastPrime = this.lastPrime) {
                null -> 2L
                2L -> 3L
                else -> {
                    if (knownPrimes.last() > lastPrime ) {
                        knownPrimes[knownPrimes.binarySearch(lastPrime) + 1]
                    } else {
                        val np = generateSequence(lastPrime+2) { it+2 }
                                .first { it.isPrime() }
                        knownPrimes.add(np)
                        np
                    }
                }
            }
            this.lastPrime = nextPrime
            return nextPrime
        }
    }
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-12-20 20:09:34

我不喜欢这样返回继承Sequence<Long>的内联对象的想法。Kotlin有几个特性可以帮助您构建东西,包括一个用于序列的特性。

使用Kotlin中的sequence构建器的强大功能(在表面下面是内部使用可悬浮函数 ),我们可以逐个实现yield,而不是实现Iterator

我们可以重写代码以使用外部object来保持全局状态,然后使用函数生成序列。

代码语言:javascript
复制
object Primes {
    private val knownPrimes: MutableList<Long> = mutableListOf(2L, 3L)
    private fun Long.isMultipleOf(n: Long) = (this % n == 0L)

    private fun Long.isPrime() = knownPrimes
            .takeWhile { it * it <= this }
            .none { this.isMultipleOf(it) }

    fun sequence(): Sequence<Long> {
        var lastPrime: Long? = null
        return sequence {
            while (true) {
                val nextPrime = when(val actualLastPrime = lastPrime) {
                    null -> 2L
                    2L -> 3L
                    else -> {
                        if (knownPrimes.last() > actualLastPrime) {
                            knownPrimes[knownPrimes.binarySearch(actualLastPrime) + 1]
                        } else {
                            val np = generateSequence(actualLastPrime + 2) { it+2 }
                                .first { it.isPrime() }
                            knownPrimes.add(np)
                            np
                        }
                    }
                }
                lastPrime = nextPrime
                yield(nextPrime)
            }
        }
    }
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/253690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档