https://kotlinlang.org logo
#getting-started
Title
# getting-started
d

Daniele B

09/03/2020, 3:48 PM
Let’s say I have a
data class
object:
Copy code
val state : AppState = AppState()
where:
Copy code
data class AppState (
  val loginState : LoginState = LoginState(),
  val showingDetail : Boolean = false,
)
data class LoginState (
  val loginVar : String
)
if I want to just change a child property, it’s very simple, it just takes 1 line:
Copy code
state = state.copy(showingDetail = true)
but it I want to change the property of one child, I need 3 lines:
Copy code
var login = state.loginState
login = login.copy(loginVar = "my value")
state = state.copy(loginState = login)
is there a simpler syntax to achieve this?
t

Tobias Berger

09/03/2020, 3:52 PM
I mean, you could do the same in a single line:
Copy code
state = state.copy(loginState = state.loginState.copy(loginVar = "my value"))
I'm just not sue if that makes it better
If you want to keep your objects immutable and want to change something on a deeper level, there is probably no other way than cascading through the structure like that. Of course you could implement additional function to hide that complexity.
just to be a bit creative: you could also write it like this:
Copy code
state = state.run { copy(loginState = loginState.copy(loginVar = "my value")) }
d

Daniele B

09/03/2020, 3:58 PM
I am was looking into writing additional functions. Ideally I would like to update an inner object with a function like this:
Copy code
updateLoginState(loginVar = "my value")
but I don’t know how to write a function that, which takes the same arguments of copy
Copy code
fun updateLoginState (I DON'T KNOW HOW TO DEFINE THE ARGUMENTS) {
	var login = state.loginState
	login = login.copy(ARGUMENTS)
	state = state.copy(loginState = login)
}
t

Tobias Berger

09/03/2020, 4:04 PM
there is no way to automatically do that, so you will just have to write them explicitly, like any other function parameter
d

Daniele B

09/03/2020, 4:06 PM
so, is
copy
a very special function?
t

Tobias Berger

09/03/2020, 4:06 PM
it's not special, it's just automatically generated...
d

Daniele B

09/03/2020, 4:07 PM
so, I guess the Kotlin language doesn’t allow similar functionality for custom functions
t

Tobias Berger

09/03/2020, 4:08 PM
the generated copy of you LoginState would look like this:
Copy code
data class LoginState (
  val loginVar : String
) {
  fun copy(loginVar: String = this.loginVar) : LoginState { 
    return LoginState(loginVar)
  }
}
d

Daniele B

09/03/2020, 4:11 PM
thanks, interesting to visualize that
t

Tobias Berger

09/03/2020, 4:11 PM
If you want that updateLoginState functionality (esp. if LoginState has multiple properties instead of just one) you can implement it manually, but it will not be automatically generated and if you change the class, you will have to update the method yourself
d

Daniele B

09/03/2020, 4:12 PM
yes, I am trying to think what would be the simplest syntax to make updates on an object like LoginState
t

Tobias Berger

09/03/2020, 4:13 PM
so you could write
Copy code
fun AppState.updateLoginState (loginVar: String = loginState.loginVar) {
	state = state.copy(loginState = LoginState(loginVar))
}
the key is to use the current values of the current
loginState
as defaults for the optional function parameters
d

Daniele B

09/03/2020, 4:14 PM
yes, I would need to manually generate that, though, which would not be feasible in case there are many properties
thanks anyway, you made me think
👍
t

Tobias Berger

09/03/2020, 4:18 PM
many properties aren't really a problem if they don't change at all. You could also consider if you really need immutability. I know it's generally considered good practice, but in some cases it just makes things more complicated without bringing any actual benefits
d

Daniele B

09/03/2020, 4:18 PM
I need to pass the state via StateFlow
so, I think it would need to be immmutable
especially I know there are immutability issues with Kotlin/Native
And I am expecting Jetpack Compose to also wanting immutable objects?
t

Tobias Berger

09/03/2020, 4:27 PM
I haven't really worked on any real android projects for years so I can't tell you anything about that. If you need immutability that's fine, just wanted to make sure you considered it.
👍 1
d

Daniele B

09/03/2020, 4:33 PM
At the moment, the simplest I am able to do is:
Copy code
updateLoginState(state.loginState.copy(loginVar = "my value"))
I would like to be able to do like this:
Copy code
updateLoginState(loginVar = "my value")
but it’s not the end of the world
my current
updateLoginState()
function is this one:
Copy code
fun updateLoginState(loginState: LoginState) {
        state = state.copy(loginState = loginState)
    }
t

Tobias Berger

09/03/2020, 4:50 PM
why not this?
Copy code
fun updateLoginState(loginVar: String) {
        state = state.copy(loginState = state.loginState.copy(loginVar = loginVar))
    }
Sure, that's the manual implementation again. But personally I'd prefer that rather than doing the copy outside.
a

Adam Powell

09/03/2020, 5:25 PM
You might be interested in arrow's optics features: https://arrow-kt.io/docs/optics/lens/
☝️ 1