Colton Idle
04/30/2024, 2:25 AMval userAddress = user?. let { user → getAddressByUserName(user) } ?: "None"
Why would you use let instead of just
val userAddress = getAddressByUserName(user ?: "None")
or just an if statement?
Maybe let
just doesn't make sense to me since english isn't my first language. why let
?Youssef Shoaib [MOD]
04/30/2024, 2:30 AMlet
is quite mathematical I guess, definitely not colloquial English.
The example you gave assumes that getAddressByUserName
can handle the input "None"
Colton Idle
04/30/2024, 2:31 AMShawn
04/30/2024, 2:48 AMShawn
04/30/2024, 2:53 AMfmap
on monads in purer functional languages, without the need to construct a monad around any of our dataShawn
04/30/2024, 2:58 AMlet
, you basically have a new scope that takes in the value you're calling let
on, and defines it
or another name within that scope with said value. It also allows you to generically return another type, likely the result of transforming the incoming valueShawn
04/30/2024, 3:00 AM?.let {}
, one use for which is to let me safely compose functions in sequence that might return nullhfhbd
04/30/2024, 4:02 AMTies
04/30/2024, 7:03 AMval userAddress = getAddressByUserName(user ?: "None")
isnt exactly the same, now the method getAddressByUserName
needs to know of the "None" condition and act accordingly (which is not a good pattern). But using an if statement is indeed generally the same thing (since it is also an expression), let
is the more concise and doesnt break the flow as muchCLOVIS
04/30/2024, 8:19 AMval userAddress = user
?.let { user -> getAddressByUserName(user) }
?: "None"
is equivalent to
val userAddress =
if (user != null) getAddressByUserName(user) ?: "None"
else "None"
I avoid ?.let {} ?:
because it's almost always ambiguous to know which cases may return the default value (it's both the initial value and the function's result). I have seen this pattern be the cause of bugs way too many times.
I only use .let
(not ?.let
), and even then, I forbid myself from using anything more complex than a single function call, preferably written as a function reference.Michael Krussel
04/30/2024, 11:19 AMuser
is a var
property of a class, then the if
statement doesn't work because the smart cast doesn't work. The let
call allows you to avoid creating a new local variable at the scope above the let
.rocketraman
04/30/2024, 11:59 AMIf user is a var property of a class,Or a
val
declared in a different module.Klitos Kyriacou
05/01/2024, 11:07 AMI avoidIt's not just withbecause it's almost always ambiguous to know which cases may return the default value?.let {} ?:
let
but this ambiguity is present with most uses of ?.
. For example:
val x = foo()?.bar() ?: throw SomeException()
This will throw if either foo()
or bar()
returns null. Sometimes, it's only foo()
that is not allowed to return null, and it's ok for bar()
to do so. The above can be corrected to this:
val x = (foo() ?: throw SomeException()).bar()