How do people decide when/whether to use .run or ....
# getting-started
t
How do people decide when/whether to use .run or .let? They do the same thing, other than how you reference the object under operation (parameter - it vs context - this). But what's the compelling reason to use on over the other? I'm particular interested in using it as a transformer on an optional variable (e.g. thing?.let .. vs thing?.run)
v
j
Usually it's a matter of whether the block is calling functions on the variable, e.g.:
Copy code
thing?.run {
   foo()
}
or passing the variable as a parameter to other functions, e.g.:
Copy code
thing?.let {
    foo(it)
}
3
t
Yeah, I've read a bunch of these that explain WHAT they are. run/let return the transform, also/apply return the original. run/apply change this to the receiver (vs the calling scope), let/also keep this in place and use it instead. For many cases one of these axes doesn't really matter. So then you end up wondering which to use. If you're an overthinker and easily prone to analysis paralysis, it's particularly annoying 😄
j
There's definitely a good amount of overlap in practice, as the block may be performing multiple operations that could be satisfied by either function. I've also used
let
at times when I'm using functions and properties with
it
as a receiver, but need to disambiguate those calls from the parent
this
scope. It really just comes down to which best fits the particular code in each scenario. There's not always a right or wrong answer.
c
I tend to avoid the
run
overload with a receiver. I use
let
for transformations, and the receiver-less run for semantic scoping:
Copy code
val foo = bar ?: run {
    log.info("something")
    return
}
e
I'm more likely to use
with(foo) { ... }
than
foo.run { ... }
, but will use
?.run { ... }
sometimes if that's what's works better
1
k
It's also possible to use both
let
and
run
to disambiguate between two different things without having to use specific names instead of `it`:
Copy code
foo().let {
    bar().run {
        // Here, you can refer to foo()'s returned value as "it" and bar()'s as "this"
    }
}
Having said that, I've never actually done this in real code.
😵 1