49 lines
1.4 KiB
Markdown
49 lines
1.4 KiB
Markdown
# Lazy Evaluation
|
|
|
|
Decodal evaluates values when they are needed.
|
|
|
|
## Lazily evaluated values
|
|
|
|
The following values are not evaluated until they are referenced or materialized:
|
|
|
|
- Module roots and top-level fields
|
|
- Object fields
|
|
- `let` bindings
|
|
- Function arguments
|
|
- `default` expressions
|
|
- Imported values
|
|
|
|
When the same binding is referenced more than once, its evaluation result is reused.
|
|
Consequently, a failure in an unreferenced field or function argument does not occur until that value is needed.
|
|
|
|
```dcdl
|
|
let
|
|
safe = 42;
|
|
unused = missing_name;
|
|
in
|
|
safe
|
|
```
|
|
|
|
This expression evaluates to `42` because it never references `unused`.
|
|
|
|
## Cycle detection
|
|
|
|
A cycle diagnostic is produced when a value being evaluated depends on itself again.
|
|
|
|
```dcdl
|
|
{
|
|
a = b + 1;
|
|
b = a + 1;
|
|
}
|
|
```
|
|
|
|
Modules and imports may refer to one another cyclically as long as the dependency graph of the fields actually evaluated is not cyclic.
|
|
|
|
## Evaluation and materialization
|
|
|
|
A normal evaluation result may retain abstract values such as constraints, `Unknown`, `default`, and functions.
|
|
Materialization converts that result to concrete data for use outside Decodal.
|
|
|
|
This separation allows schemas to be composed as values, only required fields to be evaluated, and selection of defaults to be deferred until output.
|
|
See [Materialization and Errors](./materialization-and-errors.md) for details.
|