georgeci
06/13/2024, 8:16 AMoptics
and Traversals
My data classes:
@optics
data class Foo(
val bars: List<Bar>,
) {
companion object
}
@optics
data class Bar(
val id: Int,
val flag: Boolean
) {
companion object
}
I want to copy-modify Foo
instance with change only a few Bar
in list
I can change only one element by index
val index = foo.bars.indexOfFirst { it.id == 0 }
val newFoo = Foo.bars[index].flag.set(foo, false)
Also I can change every element used Every
val newFoo = Foo.bars.every(Every.list()).flag.set(foo, false)
Is there any way to add a predicate to Every
? Like this
val newFoo = Foo.bars.every(Every.list())
.where { it.id > 100 }
.flag.set(foo, false)
Alejandro Serrano.Mena
06/13/2024, 8:32 AMset
changes the information the predicate is about?)
my suggestion in those cases is to use modify
:
val newFoo = Foo.bars.every(Every.list()).modify {
if (it.id > 100) Bar.flag.set(it, false) else it
}
(or actually, I would write it as)
val newFoo = Foo.bars.every(Every.list()).modify {
if (it.id > 100) it.copy(flag = false) else it
}
georgeci
06/13/2024, 8:33 AMdave08
06/13/2024, 9:50 AMAlejandro Serrano.Mena
06/13/2024, 11:46 AMset
The core of the problem here is to ensure that the setting does not affect the filtering... which I don't know how to do, honestly. One possibility is to have a set of "delicate optics" like filter
which can be used in some scenarios, but not in others. I'll try to write some code this afternoon...dave08
06/13/2024, 12:01 PMAlejandro Serrano.Mena
06/13/2024, 12:03 PMsimon.vergauwen
06/13/2024, 12:12 PMThis is why I think having a set of "potentially unsafe" operations could be more useful than simply restricting themI agree, in KotlinX Serialization JsonPath I also have an unsafe
Prism
to parse
, https://github.com/nomisRev/kotlinx-serialization-jsonpath/blob/9d3125957cf45958e7[…]f07de98200d8/src/commonMain/kotlin/io/github/nomisrev/optics.kt.
It's too useful to not have.dave08
06/13/2024, 12:13 PMif your filtering and setting are "disjoint"What do you mean? Isn't filtering just pinpointing a set of elements to
set()
in just like a Lens points at one? I always had trouble grasping the problem, sorry for the question 🐢...Alejandro Serrano.Mena
06/13/2024, 12:15 PMval list: List<Int> = ...
list.filter { it.isEven() }.modify { it + 1 }
what should happen here? I am filtering even numbers, but then I modify and make them odd; what should be the behavior here?dave08
06/13/2024, 12:18 PMdave08
06/13/2024, 12:19 PMAlejandro Serrano.Mena
06/13/2024, 12:34 PMdave08
06/13/2024, 12:47 PMAlejandro Serrano.Mena
06/13/2024, 7:13 PMdave08
06/16/2024, 11:16 AM* p.modify(p.modify(n) { it + 1 }) { it + 1 }
* // ---------------------- = 3
* // ---------------------------------------- = null
in the end we get null, which IS filtered... what were you expecting?Alejandro Serrano.Mena
06/16/2024, 11:47 AMdave08
06/16/2024, 11:48 AMAlejandro Serrano.Mena
06/16/2024, 11:48 AMAlejandro Serrano.Mena
06/16/2024, 11:51 AMAlejandro Serrano.Mena
06/16/2024, 11:52 AMdave08
06/16/2024, 11:57 AMAlejandro Serrano.Mena
06/16/2024, 12:26 PMdave08
06/16/2024, 12:34 PMshould not alter whether the predicate holds on the value.I don't know if most users of Arrow are familiar with these rules to know what could blow up if this rule is not kept... just stating that it's a "RULE" might not be enough to prevent users from shooting themselves in the foot... a clear example of where this is wrong would be much better... but I guess that's hard to find?
dave08
06/16/2024, 12:35 PMAlejandro Serrano.Mena
06/16/2024, 4:29 PMdave08
06/17/2024, 9:18 AM