mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 05:11:09 +00:00
163 lines
4.7 KiB
Markdown
163 lines
4.7 KiB
Markdown
# 特殊形式
|
||
|
||
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/API/special.md&commit_hash=06f8edc9e2c0cee34f6396fd7c64ec834ffb5352)
|
||
|
||
|
||
特殊形式は、Ergの型システムでは表現ができない演算子、サブルーチン(のようなもの)である。``で囲っているが、実際は捕捉できない。
|
||
また、`Pattern`や`Body`, `Conv`といった型が便宜上登場するが、そのような型が存在するわけではない。その意味もコンテクストによって異なる。
|
||
|
||
## `=`(pat: Pattern, body: Body) -> NoneType
|
||
|
||
bodyをpatに変数として代入する。同じスコープにすでに変数が存在する場合と、patにマッチしなかった場合にエラーを送出する。
|
||
また、レコードの属性定義やデフォルト引数にも使われる。
|
||
|
||
```python
|
||
record = {i = 1; j = 2}
|
||
f(x: Int, y = 2) = ...
|
||
```
|
||
|
||
bodyが型か関数であるときに`=`は特殊な振る舞いをする。
|
||
左辺の変数名を右辺のオブジェクトに埋め込むのである。
|
||
|
||
```python
|
||
print! Class() # <class <lambda>>
|
||
print! x: Int -> x + 1 # <function <lambda>>
|
||
C = Class()
|
||
print! c # <class C>
|
||
f = x: Int -> x + 1
|
||
print! f # <function f>
|
||
g x: Int = x + 1
|
||
print! g # <function g>
|
||
K X: Int = Class(...)
|
||
print! K # <kind K>
|
||
L = X: Int -> Class(...)
|
||
print! L # <kind L>
|
||
```
|
||
|
||
`=`演算子は、戻り値が「未定義」である。
|
||
多重代入、関数中での`=`は文法エラーとなる。
|
||
|
||
```python
|
||
i = j = 1 # SyntaxError: multiple assignments are not allowed
|
||
print!(x=1) # SyntaxError: cannot use `=` in function arguments
|
||
# hint: did you mean keyword arguments (`x: 1`)?
|
||
if True, do:
|
||
i = 0 # SyntaxError: A block cannot be terminated by an assignment expression
|
||
```
|
||
|
||
## `->`(pat: Pattern, body: Body) -> Func
|
||
|
||
無名関数、関数型を生成する。
|
||
|
||
## `=>`(pat: Pattern, body: Body) -> Proc
|
||
|
||
無名プロシージャ、プロシージャ型を生成する。
|
||
|
||
## `.`(obj, attr)
|
||
|
||
objの属性を読み込む。
|
||
|
||
## `|>`(obj, c: Callable)
|
||
|
||
`c(obj)`を実行する。`x + y |>.foo()`は`(x + y).foo()`と同じ。
|
||
|
||
### (x: Option T)`?` -> T
|
||
|
||
後置演算子。`x.unwrap()`を呼び出し、エラーの場合はその場で`return`する。
|
||
|
||
## match(obj, ...arms: Lambda)
|
||
|
||
objについて、パターンにマッチしたarmを実行する。armは無名関数でなくてはならない。
|
||
|
||
```python
|
||
match [1, 2, 3]:
|
||
(l: Int) -> log "this is type of Int"
|
||
[[a], b] -> log a, b
|
||
[...a] -> log a
|
||
# (1, 2, 3)
|
||
```
|
||
|
||
型指定によって処理を分岐できるが、型推論の結果は分岐に影響しない。
|
||
|
||
```python
|
||
zero: {0} -> {0}
|
||
one: {1} -> {1}
|
||
_ = match x:
|
||
i -> zero i
|
||
j -> one j # Warning: cannot reach this arm
|
||
```
|
||
|
||
## Del(x: ...T) -> NoneType
|
||
|
||
変数`x`を削除する。ただし組み込みのオブジェクトは削除できない。
|
||
|
||
```python
|
||
a = 1
|
||
Del a # OK
|
||
|
||
Del True # SyntaxError: cannot delete a built-in object
|
||
```
|
||
|
||
## do(body: Body) -> Func
|
||
|
||
引数なしの無名関数を生成する。`() ->`の糖衣構文。
|
||
|
||
## do!(body: Body) -> Proc
|
||
|
||
引数なしの無名プロシージャを生成する。`() =>`の糖衣構文。
|
||
|
||
## `else`(l, r) -> Choice
|
||
|
||
Choiceオブジェクトという2つ組のタプルのような構造体を生成する。
|
||
`l, r`は遅延評価される。すなわち、`.get_then`または`.get_else`が呼ばれたとき初めて式が評価される。
|
||
|
||
```python
|
||
choice = 1 else 2
|
||
assert choice.get_then() == 1
|
||
assert choice.get_else() == 2
|
||
assert True.then(choice) == 1
|
||
```
|
||
|
||
## 集合演算子
|
||
|
||
### `[]`(...objs)
|
||
|
||
引数から配列、またはオプション引数からディクトを生成する。
|
||
|
||
### `{}`(...objs)
|
||
|
||
引数からセットを生成する。
|
||
|
||
### `{}`(...fields: ((Field, Value); N))
|
||
|
||
レコードを生成する。
|
||
|
||
### `{}`(layout, ...names, ...preds)
|
||
|
||
篩型を生成する。
|
||
|
||
### `...`
|
||
|
||
入れ子になったコレクションを展開する。パターンマッチでも使える。
|
||
|
||
```python
|
||
[x, ...y] = [1, 2, 3]
|
||
assert x == 1 and y == [2, 3]
|
||
assert [x, ...y] == [1, 2, 3]
|
||
assert [...y, x] == [2, 3, 1]
|
||
{x; ...yz} = {x = 1; y = 2; z = 3}
|
||
assert x == 1 and yz == {y = 2; z = 3}
|
||
assert {x; ...yz} == {x = 1; y = 2; z = 3}
|
||
```
|
||
|
||
## 仮想演算子
|
||
|
||
ユーザーが直接使用できない演算子です。
|
||
|
||
### ref(x: T) -> Ref T
|
||
|
||
オブジェクトの不変参照を返す。
|
||
|
||
### ref!(x: T!) -> Ref! T!
|
||
|
||
可変オブジェクトの可変参照を返す。
|