我有一个复杂的、不可变的数据结构,其中包括简单的字段,但也包括层次结构中的映射和列表。也许我只是没有足够仔细地阅读文档,但似乎没有一个简单的方法来修改整个列表,而不做一些非常麻烦的事情。
例如,假设我有foo.bar.list,我想在索引i上添加一个元素到列表中。我看到这样做的唯一方法是使用getter获取当前列表,执行以下操作
list.subList(0, i) + listOf(newElement) + list.subList(i, list.size)把这个交给策划人。
是否有类似于list.add(index, element)或list.remove(index)的东西,您可以在镜头内调用它来修改list部件,并保持结构的其余部分不变。
或者,对于集合DSL的At、Index或Traversal部分,有什么简单的方法可以做到这一点?
发布于 2022-11-30 08:15:25
这是可能的与箭光学,和Index,正如你已经指出的。下面是一个完整的例子,
import arrow.optics.dsl.index
import arrow.optics.optics
import arrow.optics.typeclasses.Index
@optics data class Foo(val bar: Bar) {
companion object
}
@optics data class Bar(val list: List<Int>) {
companion object
}
val foo = Foo(Bar(listOf(1, 2, 3)))
fun main() {
Foo.bar.list.index(Index.list(), 1).set(foo, 5)
.let(::println) // Foo(bar=Bar(list=[1, 5, 3]))
}当然,你也可以使用光学的其他运算符。这个例子是用Kotlin1.6.21、id("com.google.devtools.ksp") version "1.6.21-1.0.6"和Arrow1.1.3编写的。
当然,如果您不喜欢使用Google,您也可以手工编写光学信息。
import arrow.optics.Lens
import arrow.optics.typeclasses.Index
data class Foo(val bar: Bar)
data class Bar(val list: List<Int>)
val bar: Lens<Foo, Bar> = Lens(Foo::bar) { foo, bar -> foo.copy(bar = bar) }
val list: Lens<Bar, List<Int>> = Lens(Bar::list) { bar, list -> bar.copy(list = list) }
val foo = Foo(Bar(listOf(1, 2, 3)))
fun main() {
val optic = (bar compose list compose Index.list<Int>().index(1))
val result = optic.modify(foo) { it + 3 }
println(result)
}https://stackoverflow.com/questions/74621154
复制相似问题