https://kotlinlang.org logo
a

Arjan van Wieringen

06/14/2021, 2:17 PM
Hi all, a high level question. I am test driving Elm and like it. However, it got me thinking of something Kotlin related. If I was to create some sort of VDOM consisting of simple data classes and compare those that would just work fine. However, when I'd include events, using some sort of 'onClick' anonymous function, the diffing will always cause to assert that the anonymous functions are different, even when they are structurally the same. As I believe Elm doesn't have this problem (because of a complete different language and compiler). Example:
Copy code
data class Node(val name: String, val onClick: () -> Unit)

fun main() {
    val a = Node("Foo") { println("Foo") }
    val b = Node("Foo") { println("Foo") }
    println(a == b) // prints "false"
}
Is there a way to obtain something similar?
a

Adam Powell

06/14/2021, 2:29 PM
#compose takes a different approach of skipping execution when inputs are unchanged instead of a vdom which sidesteps some of this class of issues. It also performs some memoization of lambdas created in
@Composable
functions as a related optimization
y

Youssef Shoaib [MOD]

06/14/2021, 2:59 PM
Also you can simply move the onClick out of the primary constructor so that the data class doesn't consider it part of the data. This should work:
Copy code
data class Node private constructor(val name: String) {
    lateinit var onClick: () -> Unit
    	private set
    constructor(name: String, onClick: () -> Unit): this(name) {
        this.onClick = onClick
    }
}

fun main() {
    val a = Node("Foo") { println("Foo") }
    val b = Node("Foo") { println("Foo") }
    println(a == b) // prints "true"
}
Also, I believe react-kotlin ran into that problem, and the workaround was to declare your functions as vals like this:
Copy code
data class Node(val name: String, val onClick: () -> Unit)

val printFoo = { println("Foo") }

fun main() {
    val a = Node("Foo", printFoo)
    val b = Node("Foo", printFoo)
    println(a == b) // prints "true"
}
a

Adam Powell

06/14/2021, 3:02 PM
not considering the callback to be part of the data tends to be a big problem here since it means if the lambda capture changes, the nodes will compare equal and not be updated with the new lambda capture
trading inefficiency when nothing has changed for incorrect behavior when something has
p

Petter Måhlén

06/15/2021, 7:16 AM
if you want to do elm-like things on the JVM, mobius might be an option. there, we chose not to pass functions around, but rather value objects. there are tradeoffs, ofc, in particular, using value objects rather than defining both when the event should be triggered, and what the event means (what action it should trigger) in one place is more verbose, but provides better separation of concerns. See https://github.com/spotify/mobius/wiki/Concepts
a

Arjan van Wieringen

06/15/2021, 1:33 PM
Sorry for the late reply! Thanks a lot for all your input, some nice answers. I
3 Views