- Every
{ }block creates a new inner scope. - Inner scopes can read variables from outer scopes.
- Inner scopes can re-assign variables declared in outer scopes.
- Variables declared with
letinside a block are not visible outside it.
let x = 10
fn show() {
let y = 20
print(x) // ✓ reads outer x
print(y) // ✓ reads local y
}
show()
print(x) // ✓ still 10
// print(y) // ✗ Name Error — y is not in scope here
Closure Semantics
Functions use lexical scoping: they capture the environment at the point of their definition, not at the point of their call.
fn make_adder(n) {
fn adder(x) {
return x + n // captures n from make_adder's scope
}
return adder
}
let add5 = make_adder(5)
let add10 = make_adder(10)
print(add5(3)) // 8
print(add10(3)) // 13
Each closure has independent state:
fn make_counter(start) {
let count = start
fn next() {
count += 1
return count
}
return next
}
let a = make_counter(0)
let b = make_counter(100)
print(a()) // 1
print(a()) // 2
print(b()) // 101 — independent from a