Elixir 学習記（2. データ型）

# Elixir学習記

| ← 前 | [目次](https://qiita.com/SF-28/items/197df5e03ab9787f40a0) | 次 → |
| :-: | :-: | :-: |
|[1. 環境構築](https://qiita.com/SF-28/items/1a4a9a71a149f42d646f) | 2. データ型 | [3. 演算子](https://qiita.com/SF-28/items/82dfb7cd5398656adbac) |

# データ型

## Integer

```elixir
100        # 10進数
0b01100100 #  2進数(binary)
0o0144     #  8進数(octal)
0x0064     # １６進数(hexadecimal)
```

## Float

```elixir
1.0
1.0e+10 # 指数表記も可能
```

## Atom

```elixir
:atom
nil
Atom # 大文字から始めると Atom になる
```

## Boolean

```elixir
true  # === :true
false # === :false
```

## String

- UTF-8でエンコードされたバイト列
- `"(ダブルクォーテーション)`で囲む

```elixir
"BitString"

# バイナリなので <> で結合する
"Bit" <> "String"

# 複数行
"""
Multi
Line
String
"""

# 式展開
var = "World"
"Hello #{var}" # == "Hello World"

"h" === <<104>>
"ł" === <<197, 130>>
```

### Binaries

- バイト列(ByteString)のことだと解釈
- `,`区切りで各バイトを定義する
- 1バイトは8ビットなので、0〜255の値を取ることができる

```elixir
<< 104, 101, 108, 108, 111 >> # → (UTF-8 Encoding) → hello
```

### BitString

- ビット列
- 長さが8の倍数になっているビット列＝バイト列

```elixir
<< 1 :: size(1) >>
```


## List

- 要素の追加/削除が想定されるデータ向き

```elixir
[1, :two, "three"]
```

### CharList(文字リスト)

- 文字(コードポイント)のリスト
- `'(シングルクォーテーション)`で囲む
- **String とは別物**
    - 基本はStringを使うが、古いライブラリの利用時等はこちらを使うこともあるらしい

```elixir
'CharList'

# リストなので ++ で結合する
'Char' ++ 'List'

'h' === [104]
'ł' === [322]
```

## Tuple

- 扱う要素が決まっているデータ向き
- 各要素へのアクセスや、要素数の取得はListより高速

```elixir
{1, :two, "three"}
```

## KeywordList

- List＋Tuple＋Atom
- 以下の特徴を持つ
    - 順序がある
    - 同じキーの要素を複数入れられる
    - キーはAtomのみ
- 関数のoptionsなどで利用される

```elixir
[a: 1, b: 2]
[{:a, 1}, {:b, 2}] # AtomをキーにしたTupleのList
```

## Map

- ハッシュテーブル構造
- Keyword Listと対比すると以下特徴を持つ
    - 順序がない
    - 同じキーの要素は1つのみである
    - パターンマッチングが行える
    - Atom以外もキーに使える

```elixir
%{a: 1, b: 2}
%{:a => 1, :b => 2, "c" => 3} # Atom以外もキーに指定可
```

## Function(無名関数)

```elixir
fn a, b -> a + b end
&(&1 + &2)
```
# 参考資料

- [Elixir 公式ガイド](https://elixir-lang.jp/getting-started/introduction.html)
    - [基本型](https://elixir-lang.jp/getting-started/basic-types.html)
    - [バイナリ、文字列、文字リスト](https://elixir-lang.jp/getting-started/binaries-strings-and-char-lists.html)
    - [キーワードリストとマップ](https://elixir-lang.jp/getting-started/keywords-and-maps.html)
- [Elixir Tutorial](https://www.tutorialspoint.com/elixir/index.htm)
    - [Elixir - Data Types](https://www.tutorialspoint.com/elixir/elixir_data_types.htm)
    - [Elixir - Variables](https://www.tutorialspoint.com/elixir/elixir_variables.htm)
- [Elixir School](https://elixirschool.com/ja)
    - [基本](https://elixirschool.com/ja/lessons/basics/basics)
    - [コレクション](https://elixirschool.com/ja/lessons/basics/collections)
- [Lists vs Tuples in Elixirs](https://blog.appsignal.com/2018/08/21/elixir-alchemy-list-vs-tuples.html)



# 感想

- 数値の大きさに応じて自動でスケールされるところなど、細かい部分が便利だと思った
- 「Binaries」という言葉がわかりづらかった
    - 個人的には BitString こそ Binaries という言葉のイメージだった
- Listに要素を追加する際、先頭に加えなければ効率が落ちるというのは面倒に感じた
    - インデックスで要素にアクセスする場合など、先頭に加えてしまうと他要素が全部ずれてしまう
    - Elixir的にはあまりそういう処理をしないのかもしれない？

# おまけ

Listの先頭追加と末尾追加にかかる時間を実際に計測してみた

```elixir
# 計測用モジュールを定義
defmodule Test do
  def concat2head(a, b) do
    b ++ a
  end

  def concat2tail(a, b) do
    a ++ b
  end
end

# 引数分の長さのリストを返す無名関数
nl = &(1..&1 |> Enum.to_list())
```

## 1 ++ 100 vs 100 ++ 1

```elixir
# :timer.tc/3 で処理時間を計測(単位はµs)
n = 100
:timer.tc(Test, :concat2head, [nl.(n), [1]])
|> elem(0)
|> IO.inspect

:timer.tc(Test, :concat2tail, [nl.(n), [1]])
|> elem(0)
|> IO.inspect

# result
23
22
```

## 1 ++ 10000 vs 10000 ++ 1

```elixir
n = 10000
:timer.tc(Test, :concat2head, [nl.(n), [1]])
|> elem(0)
|> IO.inspect

:timer.tc(Test, :concat2tail, [nl.(n), [1]])
|> elem(0)
|> IO.inspect

# result
27
785
```

## 1 ++ 1000000 vs 1000000 ++ 1

```elixir
n = 1000000
:timer.tc(Test, :concat2head, [nl.(n), [1]])
|> elem(0)
|> IO.inspect

:timer.tc(Test, :concat2tail, [nl.(n), [1]])
|> elem(0)
|> IO.inspect

# result
28
16138
```

## 結論

- 末尾追加のほうだけ、要素数が増えるにつれ処理時間が増えている
- 要素数が少なければそれほど影響はない
- 要素数が大きくなる可能性がある場合、なるべく先頭から追加したほうが良さそう
- 要素の追加より取出のほうがはるかに時間がかかる(下記記事参考)
    - 処理速度を意識するときは取出のほうを強く意識すべき

https://qiita.com/zacky1972/items/b1051a597a1d62b6f6ab