sUTL
Guide · 05 / 07

5. Scope and reduction

The source is immutable root input. Scope is the local environment used while evaluating a transform. At the top level they begin as the same value, but evaluate transforms and builtins extend scope with arguments.

Use:

  • $ for root source
  • @ for caller scope
  • ^ as a selector for the current builtin scope

Most ordinary transforms use $ for input data and @ for callback arguments.

Conditional scope

The if builtin evaluates only one branch after testing cond:

{
  "&": "if",
  "cond": {"'": "^@.enabled"},
  "true": {"'": "enabled"},
  "false": {"'": "disabled"}
}

Quoting protects the branch transforms from the dictionary’s first evaluation pass.

Interactive conformance example: JavaScript is required to edit and run it.

Iteration with reduce

sUTL has no imperative loop. reduce evaluates a callback for each list item, adding these names to scope:

  • item: current list item
  • accum: previous accumulator
  • ix: zero-based item index
{
  "&": "reduce",
  "list": [1, 2, 3, 4],
  "accum": 0,
  "t": {"'": ["&+", "^@.accum", "^@.item"]}
}

Result: 10.

Interactive conformance example: JavaScript is required to edit and run it.

Scope-name caution

Compact builtins internally use a and b while folding arguments. Historical implementations can therefore behave surprisingly when an enclosing scope also uses those names. Prefer descriptive scope names such as item, value, left, or domain-specific names in new transforms.

Higher-order transforms

A callback is just another MLSNBN value. It can come from scope, source, or a library and can be invoked using ! or !!. This is how core transforms such as map, filter, and recursive algorithms are built without adding special syntax.

Next: Declarations and libraries.