# Where can I use my variable? [Syntax and values](README.md) A variable has a name and a place where that name can be used. That place is its **scope**. Imagine a small box inside a larger box: code can look for names in its own box and then the surrounding boxes. The small box is a **child scope**. Pliro uses **lexical scope**: the arrangement of your written code determines those boxes. Calling a function from somewhere else does not change its surrounding scope. **Local** names belong inside a block or function; **global** names belong at program level, outside those blocks. A **declaration** creates a name. Pliro makes it available from that point onwards. Some languages make later declarations available earlier, called **hoisting**; Pliro does not. A function can call itself, called [recursion](recursion.md). **Mutual recursion** means two functions call each other; using a later function declaration this way is not supported. **Prelude names** are the built-in names Pliro supplies before your own declarations. ## Try a name inside a block The two variables below share a spelling but belong to different scopes. The inner name is used inside the block; the outer name is used afterwards. This is called shadowing. ```pliro # language: en let message = "outside" if true: let message = "inside" say message say message ``` Predict the order before running it. You should see `inside`, then `outside`. Changing a value with `set` is different from declaring a new inner variable with `let`. ## Source-order declarations Declarations become visible in source order. A later declaration cannot be used earlier in the same scope. A function name is visible inside its own body, which permits direct recursion, but later functions are not generally hoisted. ```text function countdown(value): if value > 0: say value countdown(value - 1) ``` Mutual recursion through a later declaration is not supported by source-order name resolution. ## Scope boundaries Pliro uses lexical scope: | Construct | Scope behavior | |---|---| | Program | Own top-level scope. | | `if` body | New child scope. | | `else` body | Separate new child scope. | | Each `while` iteration | Fresh child scope. | | Each `for` iteration | Fresh child scope containing the loop variable. | | Function | New scope for parameters and direct body declarations. | | Nested block | May shadow an enclosing name. | Declaring the same name twice in one scope is an error. A child scope may shadow an outer name, as in the first example on this page. ## Assignment across scopes `set` searches the current and enclosing lexical scopes. It may update a variable, parameter, or loop variable. It may not update a user function, built-in function, or module [namespace](../concepts/modules.md). ## Built-in shadowing Standard-library aliases are ordinary prelude names and may be shadowed: ```text let say = "not a function" ``` After that declaration, `say("Hello")` attempts to call the text value and fails at runtime. Avoid reusing built-in names unless shadowing is deliberate. ## Related entries [Syntax and values](README.md) · [Built-ins](../builtins/README.md) · [Programming guides](../guides/README.md)