Elixir入門1

# Elixirとは

- 分散並列処理に強い言語
- スケールしやすい
- クラッシュからの復帰が容易
- 詳しくは[**[翻訳] Elixir - 次に来る大物Web言語**](https://qiita.com/HirofumiTamori/items/0dfdbada30c7d8f183fd)が分かりやすくて良い

# インストール
macの場合はbrewが簡単です。

```bash
brew update
brew install elixir
```
他のOSは[公式サイト](https://elixir-lang.org/install.html)参照でお願いします。

# Interactive Elixir
ターミナルで

```bash
iex
```

と入力するとInteractive Elixirが起動する。PythonやRuby、Rとかにもあるアレ。

```bash
Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.7.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 
```

1行目はErlangの情報。このInteractive Elixirを使って色々試していきます。

# 型
なんか説明怪しいな？と思ったら[ドキュメント](https://hexdocs.pm/elixir/Kernel.html)を見るかコメントお願いします。

## 数値
普通にできそうなことはできる。

```elixir
iex(1)> 12345
12345
iex(2)> 123+45
168
iex(3)> 123*45
5535
iex(4)> 12/3
4.0
```

割り算の結果は常にFloat。
`i ~~`とすることで型情報などが確認できる。

```elixir
iex(5)> i 123
Term
  123
Data type
  Integer
Reference modules
  Integer
Implemented protocols
  IEx.Info, Inspect, String.Chars, List.Chars
iex(6)> i 12/2
Term
  6.0
Data type
  Float
Reference modules
  Float
Implemented protocols
  IEx.Info, Inspect, String.Chars, List.Chars
```

割り算の結果が整数で欲しい時は`div/2`を使用。この`/2`というのは引数が2個という意味。

```elixir
iex(7)> div(12/3)
** (CompileError) iex:7: undefined function div/1

iex(7)> div(12,3)
4
iex(8)> div(12,5)
2
iex(9)> div(14,5)
2
```

端数は切り捨てである。余りを求めたい場合は`rem/2`を使う。

```elixir
iex(10)> rem(12,5)
2
iex(11)> rem(14,5)
4
```

16進数・2進数が使用できたりする。`_`は無視されるので0の多い数字を入力するときに分かりやすくできる。

```elixir
iex(12)> 0xff
255
iex(13)> 0x63 + 0x63
198
iex(14)> 0b1111 + 0x0F
30
iex(15)> 1.5e4
1.5e4
iex(16)> 1.0e2
100.0
iex(17)> 1_0000_0000
100000000
```

（追記）8進数も利用できる。

```elixir
iex(1)> 0o66
54
```

あとIntegerは最大値がなく、メモリがなくなるまで使える。

```elixir
iex(18)> 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
iex(19)> i 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Term
  10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Data type
  Integer
Reference modules
  Integer
Implemented protocols
  IEx.Info, Inspect, String.Chars, List.Chars
```

## Atom
`:atom`のように文字列の前に`:`を付けたもの。名前と値が同じになる。つまり`:atom`の値は`atom`だし、`:ok`の値は`ok`となる。

```elixir
iex(20)> :ok
:ok
iex(21)> i :ok
Term
  :ok
Data type
  Atom
Reference modules
  Atom
Implemented protocols
  IEx.Info, Inspect, String.Chars, List.Chars
```

イマイチ理解できなかったけど、多分同じ文字が同じアドレスを指すようになっているのだと思う。本来文字列同士が同じものか確かめるには1文字ずつチェックする必要があったが、Atomを使えば同じアドレスを指しているかどうかを判定するだけですむ。

- [syntax - Why is useful to have a atom type (like in elixir, erlang)? - Stack Overflow](https://stackoverflow.com/questions/32261500/why-is-useful-to-have-a-atom-type-like-in-elixir-erlang)

```elixir
iex(22)> :"hogehoge fugafuga"
:"hogehoge fugafuga"
```
↑空白を入れたい時は""でくくる。

## 文字列
UTF-8でエンコードされたバイナリ。

```elixir
iex(23)> thinking_face = "🤔"
"🤔"
iex(24)> i thinking_face
Term
  "🤔"
Data type
  BitString
Byte size
  4
Description
  This is a string: a UTF-8 encoded binary. It's printed surrounded by
  "double quotes" because all UTF-8 encoded codepoints in it are printable.
Raw representation
  <<240, 159, 164, 148>>
Reference modules
  String, :binary
Implemented protocols
  IEx.Info, Inspect, String.Chars, List.Chars, Collectable
```

Byte sizeが4となっているが`String.length/1`は正しく1文字と判定してくれる。

```elixir
iex(25)> String.length(thinking_face)
1
```

```elixir
iex(26)> "hoge:" + "fuga" 
** (ArithmeticError) bad argument in arithmetic expression: "hoge:" + "fuga"
    :erlang.+("hoge:", "fuga")
iex(26)> "hoge:" <> "fuga"
"hoge:fuga"
```
文字列の結合は`+`ではなく`<>`。

```elixir
iex(27)> "thinking_face is -> #{thinking_face}"
"thinking_face is -> 🤔"
```
Javascriptのテンプレートリテラルみたいな埋め込みは`#{変数名}`で可能。

```elixir
iex(1)> "hoge
...(1)> hoge
...(1)> hoge"
"hoge\nhoge\nhoge"
```
↑入力中に改行もできる。

## Tuple
Pythonでは<ruby>`()`<rt>parentheses</rt></ruby>でしたがElixirでは<ruby>`{}`<rt>braces</rt></ruby>で括る。

```elixir
iex(28)> tuple = {1, :two, "three"}
{1, :two, "three"}
iex(29)> {one, two, three} = tuple
{1, :two, "three"}
iex(30)> one
1
iex(31)> two
:two
iex(32)> three
"three"
```

型はバラバラでOK。分割代入も可能。特定の要素だけが欲しい時は`elem/2`や<ruby>`_`<rt>underscore</rt></ruby>を使う。

```elixir
iex(33)> elem(tuple, 1)
:two
iex(34)> {first, _, third} = tuple
{1, :two, "three"}
iex(35)> first
1
iex(36)> _
** (CompileError) iex:36: invalid use of _. "_" represents a value to be ignored in a pattern and cannot be used in expressions

iex(36)> third
"three"
```

`_`に代入された値は自動的に破棄される。この`_`の使い方はSwiftやKotlin、Goといった比較的新しい言語でよく使用されているもの。最近C#も出来るようになったとか？

Tupleは基本的に変更出来ない。Tupleを修正したければ要素を変えた新しいTupleを作成する。要素を操作したい場合はTupleではなくListやMapを使用する。

# 集合
## List

Listは<ruby>`[]`<rt>brackets</rt></ruby>で表します。

```elixir
iex(37)> list = [1, :two, "three"]
[1, :two, "three"]
```

これも型はバラバラでOK。

<ruby>配列<rt>array</rt></ruby>ではなくListなので特定の要素にアクセスするのにO(n)時間かかる。要素を先頭に追加するのはO(1)ですむけど末尾への追加はO(n)なので注意。

【追記】
Listの連結には`++`を使う。

```elixir
iex(54)> list = list ++ [4]
[1, :two, "three", 4]
iex(56)> [0] ++ list
[0, 1, :two, "three", 4]
```

なんと`--`を使うとListの引き算も可能。存在しない値を引いても大丈夫。

```elixir
iex(57)> ["foo", :bar, 42] -- [42, "bar"]
["foo", :bar]
```

【追記終】

分割代入もできる。

```elixir
iex(38)> [one, two, three] = list 
[1, :two, "three"]
iex(39)> one
1
iex(40)> two
:two
iex(41)> three
"three"
```

ただし↑のやつはListの個数が揃っている必要がある。

```elixir
iex(43)> [hoge, fuga | rest] = list
[1, 2, 3, 4, 5]
iex(44)> hoge
1
iex(45)> fuga
2
iex(46)> rest
[3, 4, 5]
```
↑先頭の何要素かだけを取り出したい場合は`|`を使う。

```elixir
iex(47)> list = [{:a, 1}, {:b, 2}, {:a, 3}]
[a: 1, b: 2, a: 3]
```
Listの要素を`<Atom, any>`のTupleにすると擬似的なkey-valueとして使える。ちなみに`list=[a: 1,b: 2,a: 3]`と宣言してもOK。

```elixir
iex(48)> list[:a]
1
```
↑このようにすると先頭から`:a`の要素を探しに行く。

## Map
ElixirではMapは`%{key => value}`という表現をする。

```elixir
iex(49)> firstmap = %{1 => 1, :two => 2, "three" => "3"}
%{1 => 1, :two => 2, "three" => "3"}
```

keyとvalueはそれぞれどんな値でも良いが、Atomにしておくと`map.key`でアクセスできる。

```elixir
iex(50)> firstmap.1  
** (SyntaxError) iex:50: syntax error before: "1"

iex(50)> firstmap.two
2
iex(51)> firstmap.three
** (KeyError) key :three not found in: %{1 => 1, :two => 2, "three" => "3"}

```

分割代入みたいなこともできる。今更感はあるけどElixirにおいては分割代入などという言葉は使用せず「パターンマッチング」というらしい。

```elixir
iex(51)> %{1 => first, "three" => third} = firstmap
%{1 => 1, :two => 2, "three" => "3"}
iex(52)> first
1
iex(53)> third
"3"
```

昔はkeyの数が大きくなると遅くなっていたらしいが今は何百万個もkeyをもつmapを作っても良いらしい。


# 参考文献
- [はじめに - Elixir](https://elixir-lang.jp/getting-started/introduction.html)
- [Elixir School 日本語訳 · Elixir School](https://elixirschool.com/ja/)
- [Elixirで試しに何か書いてみる(その1) - Qiita](https://qiita.com/HirofumiTamori/items/602d9b326cb4816c2fe6)
- [Kernel – Elixir v1.7.3](https://hexdocs.pm/elixir/Kernel.html)
- [Elixirで面食らった演算子・記法まとめ - Qiita](https://qiita.com/manji602/items/c50e3d6965e420c2369d)
- [Getting Started with Elixir | Pluralsight](https://app.pluralsight.com/library/courses/elixir-getting-started/table-of-contents)
- [Elixir Tutorial](https://www.tutorialspoint.com/elixir/)
- [Elixir: A Big-Picture Programming Language – freeCodeCamp.org](https://medium.freecodecamp.org/elixir-a-big-picture-programming-language-755dcef2fa6a)
- [The Best Tutorials To Learn Elixir For Beginners – Quick Code – Medium](https://medium.com/quick-code/the-best-tutorials-to-learn-elixir-for-beginners-3d805ebfe5d3)