6.1 KiB
演算子
この章では、Decodal の演算子の意味を定義する。
演算子一覧
| 演算子 | 形 | 種類 | 対象 | 結果 / 意味 |
|---|---|---|---|---|
. |
object.field |
field reference | object / abstract object | field value |
| call | fn(arg) |
function call | function | function result |
! |
!expr |
unary logical | concrete Bool |
concrete Bool |
- |
-expr |
unary arithmetic | concrete Int / Float |
negated number |
* |
lhs * rhs |
arithmetic | concrete Int / Float |
numeric product |
/ |
lhs / rhs |
arithmetic | concrete Int / Float |
Float quotient |
+ |
lhs + rhs |
arithmetic | concrete Int / Float |
numeric sum |
- |
lhs - rhs |
arithmetic | concrete Int / Float |
numeric difference |
== |
lhs == rhs |
equality | concrete scalar | concrete Bool |
!= |
lhs != rhs |
equality | concrete scalar | concrete Bool |
< |
lhs < rhs |
ordering | concrete Int / Float |
concrete Bool |
<= |
lhs <= rhs |
ordering | concrete Int / Float |
concrete Bool |
> |
lhs > rhs |
ordering | concrete Int / Float |
concrete Bool |
>= |
lhs >= rhs |
ordering | concrete Int / Float |
concrete Bool |
> |
> value |
comparison constraint | numeric constraint value | abstract constraint |
>= |
>= value |
comparison constraint | numeric constraint value | abstract constraint |
< |
< value |
comparison constraint | numeric constraint value | abstract constraint |
<= |
<= value |
comparison constraint | numeric constraint value | abstract constraint |
&& |
lhs && rhs |
logical | concrete Bool |
short-circuit AND |
| ` | ` | `lhs | ||
& |
lhs & rhs |
composition | value / constraint / object | constraint-preserving composition |
// |
lhs // rhs |
patch | object / value | right-biased structural patch |
default |
base default fallback |
default | abstract value | materialization fallback |
concrete scalar は String、Bool、Int、Float を指す。
++ による array concat は未導入である。
優先順位
優先順位は高い順に以下である。
- 関数呼び出しとフィールド参照
- unary
!- */+-==!=<<=>>=&&||&//default
同じ優先順位の二項演算子は左結合である。
default は右結合である。
Arithmetic operators
+ - * / は具体的な Int / Float に対する四則演算である。
詳しくは Arithmetic Expression を参照する。
Logical and comparison operators
! && || は concrete Bool に対する論理演算である。
&& と || は短絡評価される。
== != は concrete scalar value を比較する。
< <= > >= は concrete numeric value を比較する。
詳しくは Logical and Comparison Expressions を参照する。
&: 制約合成
& は値・制約・構造を合成する演算子である。
A & B
基本規則:
- 両方が制約なら、両方を満たす制約になる。
- 制約と具体値なら、具体値が制約を満たす必要がある。
- 両方が同じ具体値なら、その値になる。
- 両方が異なる具体値なら conflict になる。
- 両方が object なら、フィールドごとに合成する。
- 同じフィールドが両方にある場合、そのフィールド値を
&で合成する。 - 矛盾が発生した場合はエラーになる。
例:
Port = Int & >= 1 & <= 65535;
NarrowedPort = Port & > 443;
MyConfig = {
port = NarrowedPort default 8080;
};
Config = MyConfig & {
port = 8000;
};
Config.port は概念的には以下になる。
NarrowedPort & 8000
8000 は NarrowedPort を満たすため成功する。
一方、以下は失敗する。
BadConfig = MyConfig & {
port = 80;
};
80 は > 443 を満たさないためである。
//: patch 合成
// は右辺優先の構造的 patch 演算子である。
& が制約を保った合成であるのに対し、// は設定やスキーマを上書き・変更するために使う。
A // B
基本規則:
- 両方が object なら、フィールドごとに再帰的に patch する。
- 同じフィールドが object/object なら、さらに再帰的に patch する。
- 同じフィールドが object/object 以外なら、右辺で置き換える。
- 左辺にしかないフィールドは保持する。
- 右辺にしかないフィールドは追加する。
- 配列はデフォルトでは右辺で置き換える。
- 関数値はデフォルトでは右辺で置き換える。
つまり // は shallow merge ではなく deep patch とする。
Base = {
feature_hoge = {
enable = Bool default true;
fuga = Int default 10;
};
};
Patched = Base // {
feature_hoge = {
enable = false;
};
};
Patched は以下に相当する。
{
feature_hoge = {
enable = false;
fuga = Int default 10;
};
}
ドットパスを使うと以下のようにも書ける。
Patched = Base // {
feature_hoge.enable = false;
};
object 全体の置換
// が deep patch である場合、object 全体を置き換えたいときの escape hatch が必要になる。
候補として、replace(...) を組み込み関数として提供する。
Replaced = Base // {
feature_hoge = replace({
enable = false;
});
};
この場合、feature_hoge は再帰 patch されず、右辺の object に丸ごと置き換わる。
& と // の使い分け
& は制約を満たす具体化に使う。
ValidConfig = MyConfig & {
port = 8000;
};
// は既存構造の上書きや変形に使う。
ModifiedSchema = MyConfig // {
port = Int default 9000;
};
// は右辺優先の patch であり、左辺の制約を常に保持するとは限らない。
制約を保持したい場合は & を使う。