*Local variables vs. Scope functions (`.let` in pa...
# codingconventions
f
Local variables vs. Scope functions (
.let
in particular)
Sometimes I have a hard time to decide about when to use
.let
and when local variables should be preferred. Consider the example from https://kotlinlang.org/docs/reference/scope-functions.html#let which reads like:
Copy code
val numbers = listOf("one", "two", "three", "four")
val modifiedFirstItem = numbers.first().let { firstItem ->
    println("The first item of the list is '$firstItem'")
    if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.toUpperCase()
println("First item after modifications: '$modifiedFirstItem'")
It could be rewritten to:
Copy code
val numbers = listOf("one", "two", "three", "four")
numbers.first().let { firstItem ->
   	println("The first item of the list is '$firstItem'")
   	if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.toUpperCase().let { modifiedFirstItem ->
	println("First item after modifications: '$modifiedFirstItem'")        
}
However, in my opinion the second
.let
makes the code less readable in this second snippet. I have heard people say that local variables are not good kotlin-style and you should be using scope-functions but I couldn’t find any resources for that claim. Would be grateful for style-recommendations / resources on that.
g
local variables are not good kotlin-style
Don't listen those people Use what is more readable for this particular case
🙏 1
👍 1
For this particular example second let is overkill imo Example from doc also probably should be rewritten with local variable, but it less obvious in this case
t
I also prefer local variables in this case. I'd even go further and get rid of the first let. It just makes the code easier to read and understand. Although the kotlin docs contain examples for .let-usage like this, I think in practice the primary use is the simple null-handling you get with
?.let
g
we usually avoid usage of let for null handling, often early return reads better
t
If an early return helps in you case, I like that too (and I had some arguments with colleagues about using them). But not every null-value means that you can jump right out of your function. In my projects we use let almost exclusively for null-checking, so if you see a let call, you basically know what's happening. So in most of our cases, early returns (although we do use them when convenient) are not really better to read.
g
yeah, not only early returns, in many cases if (nullCheck) also works and reads better than ?.let
a
I love writing code and functions without locals. I also love how Kotlin allows you group computation separately from acting upon it. I'd write your code like this:
Copy code
numbers.first().let {
  Pair( it, (if (it.length >= 5) it else "!$it!").toUpperCase() )
}.also {
  println("The first item of the list is '${it.first}'" + "\n" +
        "First item after modifications: '${it.second}'") 
}
Imagine if instead of printing, you were doing something expensive with each variable (like a db call)... much easier to combine into one function and save resources
g
This code looks very cryptic for me (and non efficient because of additional allocations for paior) for such simple case
Copy code
val original = numbers.first()
val modified = if (original.length >= 5) {
   original
} else {
   "!$original!"
}.toUpperCase()
println("The first item of the list is '$number'" + "\n" +
        "First item after modifications: '$modified'")
No additional allocations, easy to refactor (extract modified to own function, move println to own function) Also you use
it
, but as soon you start adding some nested constructions,
it
becomes even more hard to understand, so you have to add names
✔️ 1
a
I started out defining lots of `val`s, because that's what I was used to from languages. The more I use Kotlin however, the more I find that chaining commands with the scope functions is both easier to read & understand and less error-prone. It's like a direct one-way path from input to output (functional style), and less mental effort. I agree that
Pair
only goes so far, but Kotlin gives you data classes and the ability to define names inline (instead of
it
and
this
). But every developer should use what works best for them, Kotlin is great because there are so many options!
f
Thanks, I find the same arguments here as in the discussions within my own team. 🙂 at least I take away that there is no clear right&wrong here