# 遅延評価 この言語はフィールド単位で遅延評価する。 ## 基本方針 ```dcdl { schema = { hoge = String; }; result = expensive(schema); } ``` `schema` のみが必要な場合、`result` は評価されない。 ## thunk 各フィールドや let 束縛は thunk として保持できる。 ```text Thunk { expr: ExprId env: EnvRef state: Unevaluated | Evaluating | Evaluated(Value) | Error } ``` 評価済み thunk は memoize する。 同じフィールドを複数回参照しても、評価は一度だけでよい。 ## 評価状態 thunk は以下の状態を持つ。 ```text Unevaluated 未評価 Evaluating 評価中 Evaluated 評価済み Error 評価失敗 ``` `Evaluating` の thunk を再度評価しようとした場合、循環依存として扱う。 ## 循環検出 ```dcdl { a = b + 1; b = a + 1; } ``` この場合、`a` または `b` を評価すると循環エラーになる。 一方、同じモジュール内または import 間に循環があっても、評価対象のフィールドが循環していなければ成功する。 ## 評価と materialize の分離 通常の評価では、制約や default を含む中間値が残ることがある。 外部へデータとして出力する段階で materialize を行う。 この分離により、以下が可能になる。 - スキーマを値として扱う。 - default を必要になるまで評価しない。 - import されたモジュールの未使用フィールドを評価しない。 - 制約だけのフィールドを中間状態として保持する。 ## 関数呼び出しとの関係 関数引数は thunk として渡せる。 関数本体内で引数が参照されたときに評価する。 任意の関数呼び出し結果をグローバルに memoize することは必須ではない。 ただし、フィールドに束縛された呼び出し結果は、そのフィールド thunk の評価結果として memoize される。