sealed class Trie<K, V> {
data class Path<K, V>(val routes: MutableMap<K, Trie<K, V>>): Trie<K, V>() {
constructor(): this(mutableMapOf())
override fun toString() = "Path${routes}"
operator fun get(key: List<K>): Trie<K, V> {
var point = this
for ((i, k) in key.withIndex()) point = try {
point.routes[k]?.asPath() ?: throw ClassCastException() }
catch (_: ClassCastException) {
if (i == key.lastIndex) {
point.routes[k]?.let { return it }
}
error(key, k)
}
return point
}
fun getOrCreatePath(key: Iterable<K>): Path<K, V> {
var point = this
for (k in key) point = try { point.routes.getOrPut(k, ::Path).asPath() }
catch (_: ClassCastException) { error(key, k) }
return point
}
operator fun set(key: List<K>, value: V) {
val containerKey = key.subList(0, key.lastIndex)
val container = getOrCreatePath(containerKey)
val k1 = key[key.lastIndex]
container.routes[k1] = Term(value)
}
private fun error(key: Iterable<K>, k: K): Nothing {
val msg = "${key.joinToString("/")} $k"
throw NoSuchElementException(msg)
}
}
data class Term<K, V>(var value: V): Trie<K, V>()
fun asPath(): Path<K, V> = this as Path
fun asTerm(): Term<K, V> = this as Term
} #Kotilndata class Trie<K, V>(var value: V?) {
constructor(): this(null)
val routes: MutableMap<K, Trie<K, V>> by lazy(::mutableMapOf)
override fun toString() =
if (value == null) "Path${routes}"
else "Bin[$value]${routes}"
fun getOrCreatePath(key: Iterable<K>): Trie<K, V> {
var point = this
for (k in key) point = point.routes.getOrPut(k, ::Trie)
return point
}
operator fun get(key: Iterable<K>): Trie<K, V> {
var point = this
for (k in key) point = point.routes[k] ?: errorNoPath(key, k)
return point
}
operator fun set(key: Iterable<K>, value: V) {
getOrCreatePath(key).value = value
}
private fun errorNoPath(key: Iterable<K>, k: K): Nothing {
val msg = "${key.joinToString("/")} @$k"
throw NoSuchElementException(msg)
}
}
其实这个 trie 本来是比较简单的,不过我的建模有问题,就写复杂了……#Kotlin 想要给一个 List<MutableList<T>> 做 Lazy 真麻烦,by 还不能放在 primary constructor 里,delegate by lazy 也不可以。
fun <T: Any> Feed<T>.takeWhile(predicate: Predicate<T>): Sequence<T> = generateSequence {
peek.takeIf(predicate)?.let { runCatching(::consume).getOrNull() }
}
fun <T> Feed<T>.takeWhile(predicate: Predicate<T>): Sequence<T> = sequence {
while (true)
if (predicate(peek)) yield(runCatching(::consume).getOrNull() ?: break)
else break
} #Kotlin sequences 好棒棒呀,一个 or 的逻辑从三行简化到了一行。
Repeat 现在需要 override fun show(write: Consumer<T>, item: R?)
因为 Fold 只能完成 from,并不能完成 to。
至于现在的 Tuple+read/show 和之前的 Fold+then/contextual 孰优孰劣,还没有定数
但现在规范化了解析失败的时候有
其实 Seq, Or, Repeat 也完全可以在 read 的时候 try catch 一下,给异常添加更多信息传下去,不过我觉得镇静模式就很好。
因为 Fold 只能完成 from,并不能完成 to。
至于现在的 Tuple+read/show 和之前的 Fold+then/contextual 孰优孰劣,还没有定数
但现在规范化了解析失败的时候有
clamUntil,还是比较好的其实 Seq, Or, Repeat 也完全可以在 read 的时候 try catch 一下,给异常添加更多信息传下去,不过我觉得镇静模式就很好。
Literate Kotlin 可以教小白了解自己的实现,但写起来很冗长,emmm……
回看那篇
回看那篇
Share
看完这段 Kotlin 代码后我哭了
🐕 duangsuse’s shared files(e.g. productive software projects, documents)