プログラミング Elixir 第四章

# 概要

[プログラミング Elixir](https://www.amazon.co.jp/dp/4274219151)

型や変数の命名規則、演算子、スコープなど、変数の基本的な知識を解説している章。

# 型

## 値型

### 整数

10, 16, 8 , 2 進数で表すことができる。10 進数では、数値の区切りに `_` を使用できる。
決まった最大値はない。

### 浮動小数点数

小数点で表す。小数点の前後に少なくとも 1 つ数値を書かなければいけない。
指数も追記することができる `0.314e1`。 IEEE 754 倍精度（double） 16 桁程度の正確さを持つ。

### アトム

コロン(`:`)で始まる、名前を表現する定数。アルファベット, 数字, `_`, `@` を使用可能で、末尾に `!`, `?` を使うことができる。ダブルクォートで囲むと任意の文字を使用できる。

`:taro`, `:is_taro?`, `:"he is taro"`

同じ値のアトムは比較すると必ず同じになる。

### 範囲

`start..end` で表す。start, end は整数。

### 正規表現

`~r{regexp}opts` のように表す。`opts` はオプション指定する場合に書く([docs 参照](http://elixir-lang.org/docs/stable/elixir/Regex.html))。
区切り文字には `{}` 以外でもアルファベット文字以外は使用できる `//` など。ただし、`//` を使用すると正規表現内に `/` が含まれる場合エスケープする必要がある。

```iex
iex> Regex.match?(~r{taro}, "yamada taro")
=> true
iex> Regex.match?(~r{taro}i, "Yamada Taro")
=> true
```

## システム型

### PID・ポート

PID はローカル・リモートプロセスへの参照で、ポートは読み書きするリソースへの参照。
カレントプロセスの PID は self で取得ができ、新しい PID は新しいプロセスを生成した時に作られる。

### リファレンス

`make_ref` でグローバルに一意なリファレンスを生成する。

## コレクション型

### タプル

順序を持ったコレクション。`{}` で囲む。

```
{:a, :b, :c}
{1, 2}
```

関数でエラーが無いときに、第一要素に `:ok` というアトムを持つタプルを返すことをよくやる。

```iex
iex> {status, file} = File.open('log.txt')
=> {:ok, #PID<0.82.0>}
```

これを利用して、成功を仮定したマッチを書くのに使う

```iex
iex> {:ok, file} = File.open('no_exist.txt')
** (MatchError) no match of right hand side value: {:error, :enoent}
```

### リスト

`[1, 2, 3]` のように書く。
他言語での配列ではなく、連結データ構造になっており、一つの head（先頭要素）と一つの tail（それ以降）からなる。head は一つの値を持ち、tail はリストになっている。これは再帰的な処理を書く際の核となる。

また、幾つかリストのための演算子がある。

```iex
iex> [1, 2] ++ [3, 4, 5]
=> [1, 2, 3, 4, 5]

iex> [1, 2, 3] -- [3, 4, 5]
=> [1, 2]

iex> 1 in [1, 2, 3]
=> true
```

### キーワードリスト

`[a: 1, b: 2, c: 3]` のように、キーと値のペアのリストを書く事ができる。

一見 Ruby の Hash のように見えるが、Ruby の Hash に近いものは次に紹介するマップで表す。
キーワードリストは、内部で 2 つの要素を持つタプルのリストに変換され、`[{:a, 1}, {:b, 2}, {:c, 3}]` と同じ意味である。

```
iex> [a: 1, b: 2, c: 3] === [{:a, 1}, {:b, 2}, {:c, 3}]
=> true
```



### マップ

キーと値のペアのコレクション。以下の様に書く。

```
%{key => value, key => value}
```

キーは文字列、タプル、アトムと様々なものを使用することができる。

```iex
iex> %{'name' => 'taro'}
=> %{'name' => 'taro'}

iex> %{{'name', 'namae'} => 'taro'}
=> %{{'name', 'namae'} => 'taro'}

iex> %{:name => 'taro'}
=> %{name: 'taro'}
```

キーの型は異なって良い

```iex
iex> %{:name => 'taro', 'address' => 'Tokyo', {:tel, :fax} => '000-1111-2222' }
=> %{:name => 'taro', {:tel, :fax} => '000-1111-2222', 'address' => 'Tokyo'}
```

式も使うことができる

```iex
iex> %{String.downcase("NAME") <> "_1" => 'taro'}
%{"name_1" => 'taro'}
```

キーワードリストと違い、同じキーを許さない

```iex
iex> %{name: 1, name: 2}
=> %{name: 2}
```

一般的に、キーワードリストはコマンドラインパラメーターやオプションの受け渡し、マップは連想配列が欲しい場合に使う。

マップの値の取り出し方は以下のようにする。

```iex
iex> nums = %{'a' => 1, 'b' => 2, 'c' => 3}
=> %{'a' => 1, 'b' => 2, 'c' => 3}

iex> nums['a']
=> 1
```

キーがアトムの場合はドットで取得できる

```iex
iex> nums = %{a: 1, b: 2, c: 3}
=> %{a: 1, b: 2, c: 3}

iex> nums.a
=> 1
```

### バイナリ

`<< >>` で囲うとバイナリ型となる。

```
iex> bin = <<1, 2>>
=> <<1, 2>>

iex> byte_size bin
=> 2
```

# 名前

Elixir の識別子には、大文字・小文字の ASCII 文字、数字、アンダースコアで構成される。末尾には `!`, `?` を使用できる。

モジュール、レコード、プロトコル、ビヘイビアは大文字始まりのキャメルケースで表される。その他の識別子は全て、小文字かアンダースコアで始まるスネークケースで表す。
アンダースコアで、その変数が使われないことを表明している。

その他、慣習などは[スタイルガイド](https://github.com/levionessa/elixir_style_guide)にまとまっている。

# 真偽値

Elixir にはブール演算のために `true`, `false`, `nil` の特別な値を用意している。
`nil` はブール演算において `false` を表す。

# 変数スコープ

Elixir はレキシカルスコープになっており、スコープの基本単位は関数である。
関数内で定義された変数は関数内でしか参照できない。また、モジュール内に変数を定義した場合は、そのモジュールのトップレベルからアクセスできず、関数からアクセスすることはできない。

## with

with を使えば、上記とは別に独自スコープを定義することができる。

```iex
iex> a = 'hoge'
=> 'hoge'
iex> b = with a = 'fuga', do: a
=> 'fuga'
iex> a
=> 'hoge'
```

with 式内で `a` に `'fuga'` を束縛しているが、外側の `a` には影響していない。

以上が Elixir の基本的な変数の型と扱いである。