Scope functions are the ones you run on a value, and provide a function to run using that value. There's two kinds of scope functions in Kotlin - the ones where the value is passed in as a parameter (let, also etc.) and the ones where it becomes this (run, apply etc). They work the same, it just changes how you interact with the value - sometimes one is more convenient or suitable than the other
it is just the default name for the parameter passed in:
// these two are the same thing
name.let { println("Hi $it") }
name.let { it -> println("Hi $it") }
// rename it to something that reads better if you like
personData.firstName.let { name -> println("Hi $name") }
People have mentioned the null-check feature, where you can make the let block only run if the value is non-null:
name?.let { println("Hi $it, looking very not-null today") }
but another use for it is creating a temporary variable. If you have a var, it's possible the value will change while you're using it, so it's common to take a copy of it (so you know your copy won't change):
var importantNumber = 123
if (importantNumber > 100) {
// but it might have just been changed by another thread / coroutine and be < 100!
doThing(importantNumber)
}
var importantNumber = 123
val copy = importantNumber
if (copy > 100) {
// the copy can't change, so we know once we've checked it, it's fine
doThing(copy)
}
since let creates a variable to pass in as a parameter, it's basically making a copy in the same way:
var importantNumber = 123
importantNumber.let { if (it > 100) doThing(it) } // safe because 'it' won't change
and that's super important for nullable vars - if you check they're null, you need to know they'll stay null. Using ?.let guarantees that the value passed in as it will be non-null, because it's a copy that's been null-checked