← Back to Docs

Scoping Rules

VDX uses block scoping. Variables declared inside { } blocks are local to that block and are destroyed when the block ends.

How scopes work

Each of these creates a new scope:

  • Class body
  • Function body
  • if / elif / else blocks
  • while loop body (new scope per iteration)

Inner scopes can read outer variables

class App {
    let x = 10;

    if (x > 5) {
        print(x);    // 10 — reads from class scope
    }
}

Inner variables don't leak out

class App {
    if (1) {
        let secret = "hidden";
        print(secret);    // works: hidden
    }

    // print(secret);    // ERROR: undefined variable 'secret'
}

Reassignment crosses scopes

You can reassign an outer variable from an inner scope:

class App {
    let count = 0;

    fn increment() {
        count = count + 1;
    }

    increment();
    increment();
    print(count);    // 2
}

While loop scoping

Each iteration of a while loop gets a fresh scope. Variables declared with let inside the loop body are recreated each iteration:

class App {
    let i = 3;
    @unsafe while (i > 0) {
        let msg = "iteration";    // fresh each time
        print(msg, i);
        i = i - 1;
    }
}

Function parameters

Function parameters live in the function's scope and do not affect outer variables with the same name:

class App {
    let x = 100;

    fn show(x) {
        print(x);    // prints the parameter, not 100
    }

    show(42);        // 42
    print(x);        // 100 — unchanged
}