Add bilingual manual and localized docs routes
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
# 演算子
|
||||
|
||||
この章では、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` | array concat | concrete arrays | concatenated array |
|
||||
| `==` | `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 || rhs` | logical | concrete `Bool` | short-circuit OR |
|
||||
| `&` | `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 |
|
||||
| `as` | `narrower as wider` | range refinement | value / constraint / structure | narrower result plus untouched right-only ranges |
|
||||
|
||||
`concrete scalar` は `String`、`Bool`、`Int`、`Float` を指す。
|
||||
|
||||
## 優先順位
|
||||
|
||||
優先順位は高い順に以下である。
|
||||
|
||||
1. 関数呼び出しとフィールド参照
|
||||
2. unary `!` `-`
|
||||
3. `*` `/`
|
||||
4. `+` `-`
|
||||
5. `++`
|
||||
6. `==` `!=` `<` `<=` `>` `>=`
|
||||
7. `&&`
|
||||
8. `||`
|
||||
9. `&`
|
||||
10. `//`
|
||||
11. `default`
|
||||
12. `as`
|
||||
|
||||
同じ優先順位の二項演算子は左結合である。
|
||||
`default` は右結合である。
|
||||
|
||||
## Arithmetic operators
|
||||
|
||||
`+` `-` `*` `/` は具体的な `Int` / `Float` に対する四則演算である。
|
||||
詳しくは [Arithmetic Expression](./expression/arithmetic.md) を参照する。
|
||||
|
||||
## Array concat operator
|
||||
|
||||
`++` は concrete array 同士を連結する演算子である。
|
||||
要素は変換されず、左辺の要素の後に右辺の要素が並ぶ。
|
||||
|
||||
```dcdl
|
||||
["read", "write"] ++ ["admin"]
|
||||
```
|
||||
|
||||
## Logical and comparison operators
|
||||
|
||||
`!` `&&` `||` は concrete `Bool` に対する論理演算である。
|
||||
`&&` と `||` は短絡評価される。
|
||||
|
||||
`==` `!=` は concrete scalar value を比較する。
|
||||
`<` `<=` `>` `>=` は concrete numeric value を比較する。
|
||||
詳しくは [Logical and Comparison Expressions](./expression/logical-and-comparison.md) を参照する。
|
||||
|
||||
## `&`: 制約合成
|
||||
|
||||
`&` は値・制約・構造を合成する演算子である。
|
||||
|
||||
```dcdl
|
||||
A & B
|
||||
```
|
||||
|
||||
基本規則:
|
||||
|
||||
- 両方が制約なら、両方を満たす制約になる。
|
||||
- 制約と具体値なら、具体値が制約を満たす必要がある。
|
||||
- 両方が同じ具体値なら、その値になる。
|
||||
- 両方が異なる具体値なら conflict になる。
|
||||
- 両方が object なら、フィールドごとに合成する。
|
||||
- 同じフィールドが両方にある場合、そのフィールド値を `&` で合成する。
|
||||
- 片方にしかないフィールドは、そのまま結果に保持する。
|
||||
- 矛盾が発生した場合はエラーになる。
|
||||
|
||||
例:
|
||||
|
||||
```dcdl
|
||||
Port = Int & >= 1 & <= 65535;
|
||||
NarrowedPort = Port & > 443;
|
||||
|
||||
MyConfig = {
|
||||
port = NarrowedPort default 8080;
|
||||
};
|
||||
|
||||
Config = MyConfig & {
|
||||
port = 8000;
|
||||
};
|
||||
```
|
||||
|
||||
`Config.port` は概念的には以下になる。
|
||||
|
||||
```text
|
||||
NarrowedPort & 8000
|
||||
```
|
||||
|
||||
`8000` は `NarrowedPort` を満たすため成功する。
|
||||
|
||||
一方、以下は失敗する。
|
||||
|
||||
```dcdl
|
||||
BadConfig = MyConfig & {
|
||||
port = 80;
|
||||
};
|
||||
```
|
||||
|
||||
`80` は `> 443` を満たさないためである。
|
||||
|
||||
## `//`: patch 合成
|
||||
|
||||
`//` は右辺優先の構造的 patch 演算子である。
|
||||
`&` が制約を保った合成であるのに対し、`//` は設定やスキーマを上書き・変更するために使う。
|
||||
|
||||
```dcdl
|
||||
A // B
|
||||
```
|
||||
|
||||
基本規則:
|
||||
|
||||
- 両方が object なら、フィールドごとに再帰的に patch する。
|
||||
- 同じフィールドが object/object なら、さらに再帰的に patch する。
|
||||
- 同じフィールドが object/object 以外なら、右辺で置き換える。
|
||||
- 左辺にしかないフィールドは保持する。
|
||||
- 右辺にしかないフィールドは追加する。
|
||||
- 配列はデフォルトでは右辺で置き換える。
|
||||
- 関数値はデフォルトでは右辺で置き換える。
|
||||
|
||||
つまり `//` は shallow merge ではなく deep patch とする。
|
||||
|
||||
```dcdl
|
||||
Base = {
|
||||
feature_hoge = {
|
||||
enable = Bool default true;
|
||||
fuga = Int default 10;
|
||||
};
|
||||
};
|
||||
|
||||
Patched = Base // {
|
||||
feature_hoge = {
|
||||
enable = false;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
`Patched` は以下に相当する。
|
||||
|
||||
```dcdl
|
||||
{
|
||||
feature_hoge = {
|
||||
enable = false;
|
||||
fuga = Int default 10;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
ドットパスを使うと以下のようにも書ける。
|
||||
|
||||
```dcdl
|
||||
Patched = Base // {
|
||||
feature_hoge.enable = false;
|
||||
};
|
||||
```
|
||||
|
||||
## object 全体の置換
|
||||
|
||||
`//` では object/object は常に deep patch される。
|
||||
object field 全体を特別に置き換えるための `replace(...)` 構文や組み込み関数は core には含めない。
|
||||
|
||||
object 全体を別構造にしたい場合は、patch 対象より外側で値を作り直す。
|
||||
|
||||
## `as`: range refinement
|
||||
|
||||
`as` は左辺が右辺より具体的で狭い範囲であることを確認する、非対称な絞り込み演算子である。
|
||||
|
||||
```dcdl
|
||||
Refined = {
|
||||
port = 8000;
|
||||
} as {
|
||||
port = Int & >= 1 & <= 65535;
|
||||
host = String;
|
||||
enabled = Bool default true;
|
||||
};
|
||||
```
|
||||
|
||||
`port` は左辺の `8000` に具体化される。
|
||||
右辺にしかない `host` と `enabled` は abstract のまま結果へ残る。default の有無は、右辺だけの field を保持するかどうかに影響しない。
|
||||
`as` 自体は default を選択せず、後から結果を materialize した場合だけ通常の default 規則が働く。
|
||||
|
||||
左辺にしかない object field は右辺の field domain 外なのでエラーになる。
|
||||
両側にある nested object、array constraint、map constraint は同じ規則で再帰的に絞り込む。
|
||||
|
||||
abstract range 同士も包含を確認できる。
|
||||
|
||||
```dcdl
|
||||
Int & > 10 as Int & > 0 # 成功し、Int & > 10 を返す
|
||||
Int as Int & > 0 # 失敗
|
||||
```
|
||||
|
||||
`&` は対称な合成であり、片方だけにある object field を保持する。
|
||||
したがって、左右に方向を持つ絞り込みを `&` で代用しない。
|
||||
詳細は [Range Refinement](./expression/ascription.md) を参照する。
|
||||
|
||||
## `&`、`//`、`as` の使い分け
|
||||
|
||||
`&` は制約や部分構造を失わず、対称に合成する。
|
||||
|
||||
```dcdl
|
||||
Combined = MyConfig & {
|
||||
port = 8000;
|
||||
};
|
||||
```
|
||||
|
||||
`//` は既存構造の上書きや変形に使う。
|
||||
|
||||
```dcdl
|
||||
ModifiedSchema = MyConfig // {
|
||||
port = Int default 9000;
|
||||
};
|
||||
```
|
||||
|
||||
`//` は右辺優先の patch であり、左辺の制約を常に保持するとは限らない。
|
||||
制約を保持したい場合は `&` を使う。
|
||||
|
||||
左辺が右辺より狭いことを検証しながら合成する場合は `as` を使う。
|
||||
|
||||
```dcdl
|
||||
RefinedConfig = NarrowConfig as WideConfig;
|
||||
```
|
||||
Reference in New Issue
Block a user