erg/doc/JA/syntax/quick_tour.md
Shunsuke Shibayama 96132b20f6 initial commit
2022-08-10 23:02:27 +09:00

267 lines
5 KiB
Markdown

# Quick Tour
`syntax`以下のドキュメントは、概ねプログラミング初心者でも理解できることを目指して書かれています。
すでにPythonやRust, Haskellなどの言語を習得されている方にとっては、少し冗長であるかもしれません。
そこで以下では概説的にErgの文法を紹介します。
特に言及のない部分はPythonと同じと考えてください。
## 変数、定数
変数は`=`で定義します。Haskellと同じように、一度定義した変数は書き換えられません。ただし別のスコープではシャドーイングできます。
```erg
i = 0
if True:
i = 1
assert i == 0
```
大文字で始まるものは定数です。コンパイル時計算できるものだけが定数にできます。
また、定数は定義以降すべてのスコープで同一です。
```erg
PI = 3.141592653589793
match random.random!(0..10):
PI:
log "You get PI, it's a miracle!"
```
## 宣言
Pythonと違い、変数の型のみを先に宣言することが可能です。
当然、宣言の型と実際に代入されるオブジェクトの型は互換していなくてはなりません。
```erg
i: Int
i = 10
```
## 関数
Haskellと同じように定義できます。
```erg
fib 0 = 0
fib 1 = 1
fib n = fib(n - 1) + fib(n - 2)
```
無名関数は以下のように定義できます。
```erg
i -> i + 1
assert [1, 2, 3].map(i -> i + 1).to_arr() == [2, 3, 4]
```
## 演算子
Erg独自の演算子は以下の通りです。
### 可変化演算子(!)
Ocamlの`ref`のようなものです。
```erg
i = !0
i.update! x -> x + 1
assert i == 1
```
## プロシージャ
副作用のあるサブルーチンはプロシージャと呼ばれ、`!`がついています。
```erg
print! 1 # 1
```
## ジェネリック関数(多相関数)
```erg
id|T|(x: T): T = x
id(1): Int
id("a"): Str
```
## レコード
ML系言語にあるレコード(あるいはJSのオブジェクトリテラル)に相当するものを利用できます。
```erg
p = {x = 1; y = 2}
```
## 所有権
Ergは可変オブジェクト(`!`演算子で可変化したオブジェクト)に所有権がついており、複数の場所から書き換えられません。
```erg
i = !0
j = i
assert j == 0
i # MoveError
```
対して不変オブジェクトは複数の場所から参照できます。
## 可視性
変数の頭に`.`をつけると、その変数は公開変数となり、外部モジュールから参照できるようになります。
```erg
# foo.er
.x = 1
y = 1
```
```erg
foo = import "foo"
assert foo.x == 1
foo.y # VisibilityError
```
## パターンマッチ
### 変数パターン
```erg
# basic assignment
i = 1
# with type
i: Int = 1
# function
fn x = x + 1
fn: Int -> Int = x -> x + 1
```
### リテラルパターン
```erg
# if `i` cannot be determined to be 1 at compile time, TypeError occurs.
# short hand of `_: {1} = i`
1 = i
# simple pattern matching
match x:
1 -> "1"
2 -> "2"
_ -> "other"
# fibonacci function
fib 0 = 0
fib 1 = 1
fib n: Nat = fib n-1 + fib n-2
```
### 定数パターン
```erg
PI = 3.141592653589793
E = 2.718281828459045
num = PI
name = match num:
PI -> "pi"
E -> "e"
_ -> "unnamed"
```
### 破棄(ワイルドカード)パターン
```erg
_ = 1
_: Int = 1
right(_, r) = r
```
### 可変長パターン
後述するタプル/配列/レコードパターンと組み合わせて使う。
```erg
[i, ...j] = [1, 2, 3, 4]
assert j == [2, 3, 4]
first|T|(fst: T, ...rest: T) = fst
assert first(1, 2, 3) == 1
```
### タプルパターン
```erg
(i, j) = (1, 2)
((k, l), _) = ((1, 2), (3, 4))
# ネストしていないなら()を省略可能(1, 2は(1, 2)として扱われる)
m, n = 1, 2
```
### 配列パターン
```erg
length [] = 0
length [_, ...rest] = 1 + length rest
```
#### レコードパターン
```erg
{sin; cos; tan; ...} = import "math"
{*} = import "math" # import all
person = {name = "John Smith"; age = 20}
age = match person:
{name = "Alice"; _} -> 7
{_; age} -> age
```
### データクラスパターン
```erg
Point = Inherit {x = Int; y = Int}
p = Point.{x = 1; y = 2}
Point.{x; y} = p
```
## 内包表記
```erg
odds = [i | i <- 1..100; i % 2 == 0]
```
## クラス
Ergでは多重・多段継承をサポートしていません。
## トレイト
Rustのトレイトと似ていますが、より本来の意味に近いもので、合成や分離ができ、属性とメソッドは対等に扱われます。
また、実装を伴いません。
```erg
XY = Trait {x = Int; y = Int}
Z = Trait {z = Int}
XYZ = XY and Z
Show = Trait {show: Self.() -> Str}
@Impl XYZ, Show
Point = Class {x = Int; y = Int; z = Int}
Point.
...
```
## パッチ
クラスやトレイトに実装を与えたりできます。
## 篩型
述語式で型に制限をかけられます。
```erg
Nat = {I: Int | I >= 0}
```
## 値を含むパラメトリック型(依存型)
```erg
a: [Int; 3]
b: [Int; 4]
a + b: [Int; 7]
```