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