> ## Documentation Index
> Fetch the complete documentation index at: https://docs.penbox.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic evaluation & scope

> Local variables, deferred evaluation, and value pipelines in penscript

penscript supports local variable definitions, deferred evaluation, and value pipelines. These operators let you break complex expressions into readable parts, build reusable templates, and chain transformations step by step.

## Local Variables: `:define` + `:in`

Defines local variables that are available only within the `:in` expression. Variables can reference each other sequentially — each definition can use variables defined before it.

```json theme={null}
{
  ":define": [
    { "t": "{s} {s}" },
    { "u": "{t} {t}" }
  ],
  ":in": "{u}"
}

// Scope: { "s": "hello" }
// Result: "hello hello hello hello"
```

Variables can be computed using operators:

```json theme={null}
{
  ":define": [
    { "base_premium": { ":product": [0.7355, "{data.horses_power}"] } },
    { "tax": { ":multiply": ["{base_premium}", 0.21] } },
    { "total": { ":sum": ["{base_premium}", "{tax}"] } }
  ],
  ":in": "Total premium: {total}"
}

// Scope: { "data": { "horses_power": 110 } }
// Result: "Total premium: 97.7"
```

This is essential for complex calculations where intermediate values improve readability and avoid repeating expressions.

## Inline Local Bindings: `:with`

Creates local variable bindings directly within an expression — typically inside a `:map`. The first argument defines the variables, the second is the expression that uses them.

```json theme={null}
{
  ":with": [
    { "pos": { ":sum": ["{@index}", 1] } },
    { "title": "Person {pos}" }
  ]
}

// Inside a :map where @index is 0:
// Result: { "title": "Person 1" }
```

The difference from `:define`/`:in`: `:with` is designed for use inside loops and transformations where you need a quick local binding without a full `:define` block.

**Generating complex dynamic structures:**

```json theme={null}
{
  ":map": [
    { ":range-array": [0, "{data.count}"] },
    {
      ":with": [
        { "pos": { ":sum": ["{@index}", 1] } },
        [
          { "type": "paragraph", "title": "Person {pos}" },
          { "key": "name_{@index}", "type": "text", "title": "Person {pos} name" },
          { "key": "email_{@index}", "type": "email", "title": "Person {pos} email" }
        ]
      ]
    }
  ]
}

// Scope: { "data": { "count": 2 } }
// Result:
// [
//   { "type": "paragraph", "title": "Person 1" },
//   { "key": "name_0", "type": "text", "title": "Person 1 name" },
//   { "key": "email_0", "type": "email", "title": "Person 1 email" },
//   { "type": "paragraph", "title": "Person 2" },
//   { "key": "name_1", "type": "text", "title": "Person 2 name" },
//   { "key": "email_1", "type": "email", "title": "Person 2 email" }
// ]
```

## Raw Expressions: `:raw`

Captures an expression without evaluating it. The result is the expression structure itself (the AST), not the evaluated value. This is the foundation for building reusable expression templates.

```json theme={null}
{ ":raw": ["{a}", "{a}"] }

// Scope: { "a": 42 }
// Result: ["{a}", "{a}"]   (not evaluated — still contains variable references)
```

Defining a reusable template with `:define`:

```json theme={null}
{
  ":define": [
    { "exp": { ":raw": ["{value}", "{value}"] } }
  ],
  ":in": "{exp}"
}

// Scope: { "value": 5 }
// Result: ["{value}", "{value}"]   (still raw)
```

The raw expression is stored for later evaluation with `:eval`.

## Dynamic evaluation: `:eval`

Evaluates an expression that was previously captured with `:raw` or built dynamically. This is the counterpart to `:raw` — it takes a stored expression and runs it in the current scope.

**Simple evaluation:**

```json theme={null}
{ ":eval": { ":sum": [1, 2, 3] } }
// Result: 6
```

**Combined with `:raw` for reusable templates:**

```json theme={null}
{
  ":using": {
    "duplicateInArray": { ":raw": ["{a}", "{a}"] }
  },
  ":eval": "{duplicateInArray}"
}

// Scope: { "a": 7 }
//
// Evaluation steps:
// 1. "duplicateInArray" is defined as a raw expression ["{a}", "{a}"]
// 2. :eval resolves "{duplicateInArray}" to that raw expression
// 3. The raw expression is evaluated in a child scope where "a" is 7
//
// Result: [7, 7]
```

The `:using` operator defines named expressions — like `:define`, but specifically designed for storing expression templates that `:eval` will run.

## Pipelines: `:pipe`

Passes a value through multiple transformation steps sequentially. Each step receives the result of the previous step as `@value`.

```json theme={null}
{
  ":pipe": [
    "{data.raw_amount}",
    { ":sum": ["@value", 1] },
    { ":multiply": ["@value", 2] }
  ]
}

// Scope: { "data": { "raw_amount": 10 } }
//
// Flow:
// step 1 → 10
// step 2 → 10 + 1 = 11
// step 3 → 11 × 2 = 22
//
// Result: 22
```

Pipelines are useful when a value needs to pass through a series of transformations — adding fees, applying tax rates, rounding — where each step depends on the result of the previous one. The `@value` context variable always contains the output of the most recent step.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Variables & scope" icon="brackets-curly" href="/penscript/variables">
    Scope and variable resolution
  </Card>

  <Card title="Loops & arrays" icon="repeat" href="/penscript/arrays">
    :with inside :map
  </Card>

  <Card title="Numbers & calculations" icon="calculator" href="/penscript/numbers">
    Calculations in :define and :pipe
  </Card>

  <Card title="How penscript works" icon="gears" href="/penscript/how_it_works">
    Dynamic evaluation examples
  </Card>
</CardGroup>
