Scope

Every function and block ({ ... }) introduces a new scope for declarations. Each function and block can refer to declarations in its scope or any of the outer scopes.

1
let x = 10
2
3
fun f(): Int {
4
let y = 10
5
return x + y
6
}
7
8
f() // is `20`
9
10
// Invalid: the identifier `y` is not in scope.
11
//
12
y
1
fun doubleAndAddOne(_ n: Int): Int {
2
fun double(_ x: Int) {
3
return x * 2
4
}
5
return double(n) + 1
6
}
7
8
// Invalid: the identifier `double` is not in scope.
9
//
10
double(1)

Each scope can introduce new declarations, i.e., the outer declaration is shadowed.

1
let x = 2
2
3
fun test(): Int {
4
let x = 3
5
return x
6
}
7
8
test() // is `3`

Scope is lexical, not dynamic.

1
let x = 10
2
3
fun f(): Int {
4
return x
5
}
6
7
fun g(): Int {
8
let x = 20
9
return f()
10
}
11
12
g() // is `10`, not `20`

Declarations are not moved to the top of the enclosing function (hoisted).

1
let x = 2
2
3
fun f(): Int {
4
if x == 0 {
5
let x = 3
6
return x
7
}
8
return x
9
}
10
f() // is `2`