Scope Chain Walk

Block tags that shift local scope — {#each} and {#with} — push a new scope link onto the engine’s scope chain. The ..\ operator walks the chain backward one level per occurrence, letting an inner tag reference data from an outer scope.

Basic syntax

{..\Expression} — walk one level back, then bind Expression against that outer scope. The operator can be chained: {..\..\Expression} walks two levels back.

TagMeaning
{..\Name}One level out, then bind Name
{..\..\Title}Two levels out, then bind Title
{..\$}One level out, then reference local scope at that level
{..\Address.City}One level out, then dotted access through Address

Example

Data:
var report = new
{
    Title = "Quarterly Sales",
    Departments = new[]
    {
        new
        {
            Name = "Sales",
            Reps = new[]
            {
                new { Name = "Alice" },
                new { Name = "Bob" }
            }
        }
    }
};
Template:
{Title}
{#each Departments}
  {Name}:
  {#each Reps}
  - {Name} (dept: {..\Name}, report: {..\..\Title})
  {/each}
{/each}
Result:
Quarterly Sales
  Sales:
  - Alice (dept: Sales, report: Quarterly Sales)
  - Bob (dept: Sales, report: Quarterly Sales)

In the innermost block, local scope is a Rep. One walk back lands at the Department. Two walks back lands at the report root.

When to prefer variables instead

Walking with ..\ is concise for one or two levels deep. Beyond that, the operators stack up and the tag becomes hard to read at a glance. Declaring a variable in the outer scope is usually cleaner once you cross two levels or need the same outer value at multiple points inside an inner block.

With walk:
{#each Departments}
  {#each Reps}
  - {Name}, {..\Name}, {..\..\Title}
  {/each}
{/each}
With variables:
{?var:reportTitle = Title}
{#each Departments}
  {?var:deptName = Name}
  {#each Reps}
  - {Name}, {:deptName}, {:reportTitle}
  {/each}
{/each}

See Variables for declaration, reassignment, and lifetime rules.

Walks inside {#with} blocks

{#with} blocks shift scope just like {#each} iterations do. ..\ walks back through a with-shift exactly the same way:

{#with Person.Address}
  {City}, {..\Name.First}'s primary address
{/with}

The walk distance counts each scope shift — both {#each} iterations and {#with} blocks contribute one level. Partial templates do not push a new walkable level; a partial inherits its caller’s scope chain.

Limits

The walk cannot go above the root scope. Exceeding the number of pushed scopes raises a MergeException.

Next steps

  • With Blocks — explicit scope shifts as an alternative composition pattern
  • Variables — declared variables are usually cleaner past two levels of walk depth
  • Iteration — the most common source of walkable scopes