```data class Form( .. val fields: Fields ...
# getting-started
u
Copy code
data class Form(
    ..
    val fields: Fields
) {
    data class Fields(
        val personalNumber: InputField,
        ...
    )
}

data class InputField(
    val value: String,
    ..
}
this is my model I want to update
value
obviously its a copy of a copy of a copy, which is ugly, I want to stuff into a extension
Copy code
private fun <T> Form.updatePersonalNumberValue(value: String): Form {
    val field = fields.personalNumber.copy(value = value)
    copy(fields = fields.copy(personalNumber = field)
}
works but obviously doesn't scale as I have 20 fields, is there a way to make this generic somehow?
Copy code
private fun Form.updateFieldValue(selector: (Form.Fields) -> InputField, value: String) {
I was thinking something like this, a selector lambda
val field = selector(fields)
however how do I assign it back to the
Form
? So seems like a dead end. It seems I can only do
Fields -> Fields
lambda at best Is this really the best you can do in kotlin?
Copy code
form.updateFields {
    copy(
    	personalNumber = personalNumber.copy(
    		value = "new personal number"
		)
	)
}
TLDR; is there a way to generically select a copy parameter?
y
The pattern you're looking for is called
Lens
. I would recommend using something like Arrow Optics to generate those lenses for you either at compile-time or runtime.
u
I really don't want a library for what essentially is just a
form.fields.personaNumber.value = x
I could live with a
Copy code
updateFields(
	selector = { it.personalNumber },
	updater = { it.copy(value = "x")}
)
y
You can roll your own if you'd like. https://github.com/dmcg/gilded-rose-tdd/blob/main/src/main/java/com/gildedrose/foundation/lenses.kt This is a very good one-file implementation
u
so what would be the final syntax? am I not just trading
copy
for
update
?
y
Copy code
val personalNumberValueLens = Form::fields.asLens() andThen Fields::personalNumber.asLens() andThen InputField::value.asLens()
val form2 = form.with(personalNumberValueLens, "x")
You can define your own
andThen
that uses properties directly
u
oh boy, guess Im gonna tolerate 2
copy
calls 😕
isnt value semantics coming to kotlin? atleast the sugar? dont reall care about the jvm values which are 10 years in making
y
There's only design notes available, but it's something that should be focused on more after K2 is out
u
any idea on the ETA of the K2?
c
"Sometimes this year" I wouldn't be surprised if it happened around KotlinConf (May–June)
k
Is this a violation of the Law of Demeter? (Probably not, as these are just plain data classes, but worth thinking about.)
c
Value semantics come from FP and have very different maintainability rules than OOP. Especially because stuff is immutable.