Saltar al contenido

03 · Variables y Bindings

Shadowing y Alcance

Redeclarar un nombre con let (shadowing) y cómo el alcance léxico define el tiempo de vida de un binding.

En esta página

El shadowing consiste en redeclarar un nombre con un nuevo let. Cada let crea un binding completamente nuevo — el anterior queda inaccesible, sin necesidad de mut. Es útil en pipelines de transformación donde el nombre lógico permanece igual pero el tipo o el valor cambia en cada paso:

let value = "42" → let value = 42 → let value = value * 2; cada let crea un binding nuevo.

05-shadowing.zolo
Playground
// Feature: Shadowing — redeclaring a name with `let`
// Syntax: `let x = ...` followed by another `let x = ...`
// When to use: transform a value in stages while keeping the same
// name (parse → validate → normalize), change a variable's type
// during a pipeline. Unlike `mut`, every `let` creates a NEW
// binding; the previous one becomes inaccessible.

// Shadowing with type change.
let value = "42"  // str
let value = 42  // int (new binding)
let value = value * 2  // int = 84
print(value)  // 84

// Useful for "cleaning" data in a pipeline.
let raw = "  Hello  "
let raw = raw.trim()  // "Hello"
let raw = raw.to_upper()  // "HELLO"
print(raw)  // HELLO

// Shadowing inside blocks (scope).
let x = 10
{
  let x = 100  // shadows only inside the block
  print(x)  // 100
}
print(x)  // 10 (outer binding intact)

// Difference vs `mut`:
//   - `let mut x = 1; x = 2`     -> same binding, new value
//   - `let x = 1; let x = 2`     -> new binding, still immutable
let count = 1
let count = count + 1
let count = count + 1
print(count)  // 3 (each `let` creates a fresh binding)

El alcance léxico determina dónde se puede usar un binding. Cada bloque { ... } abre un nuevo alcance: los bindings declarados dentro mueren al cerrar } y no se filtran hacia afuera. Las funciones, if, for y while siguen la misma regla:

Los bindings internos no existen fuera del bloque; if let restringe el binding a la rama verdadera.

09-scoping.zolo
Playground
// Feature: Lexical binding scope

// Syntax: bindings live in the `{ ... }` they were declared in

// When to use: to understand when a variable "dies" and where it

// can be used. Zolo uses lexical scoping, like Rust and JS `let`.


// A nested block has its own scope.

let outer = "outside"
{
  let inner = "inside"
  print(outer)  // outside — outer visible

  print(inner)  // inside

}

// inner does not exist anymore here (uncomment to test):

// print(inner)  // error: undefined variable


print(outer)  // outside


// Function scope — params and local bindings disappear on return.

fn compute(n: int) -> int {
  let doubled = n * 2
  let result = doubled + 10
  return result
}

print(compute(5))  // 20


// `doubled` and `result` did not leak outside.


// `if`/`for`/`while` introduce a new scope.

var acc = 0
for i in 1..=3 {
  let squared = i * i  // lives only inside the loop

  acc = acc + squared
}
print(acc)  // 1 + 4 + 9 = 14


// `if let` bindings only apply inside the true branch.

let value: int? = 42
if let v = value {
  print("inside: {v}")  // v exists here

}
// v does not exist outside.

Desafío

En el ejemplo de shadowing, reemplaza los let sucesivos por un único let mut con reasignaciones. La salida final debe ser la misma — compara ambos enfoques y decide cuál expresa mejor la intención.

Índice global

Encuentra tu camino por Zolo

Prueba una idea

Empieza aquí

9 resultados

9 resultados

enespt-br