Scope
Prerequisites: Functions
Scope is the region of code where a name can be used. Every pair of curly braces creates a new scope.
Real-world analogy: scopes are nested rooms. From an inner room you can see into the rooms around it, but people outside can't see in.
Example
const val TAX_RATE = 0.2 // top level: visible everywhere in the file
fun total(price: Double): Double {
val tax = price * TAX_RATE // inner code can see outer names
return price + tax
}
fun main() {
println(total(100.0))
if (true) {
val message = "inside"
println(message)
}
}
120.0
inside
TAX_RATEis declared at the top level of the file, so every function can use it.taxexists only insidetotal.messageexists only inside theifbraces.
Using a name outside its scope is a compile error:
fun main() {
if (true) {
val message = "inside"
}
println(message)
}
error: unresolved reference 'message'.
Shadowing
An inner scope can declare a name that hides an outer one. IntelliJ warns about it ("Name shadowed"), because it's easy to confuse the two — usually it's better to pick a different name.
Keep scope small
Declare values close to where they're used, and pass values into functions as parameters rather than reading many outside variables. Mutable top-level variables in particular make programs hard to follow.