Elixirのチートシートを作ろう #3

# 1. OverView

さて、いきなりですが、コレクションです。
コレクションコレクション、やっほーやっほー…それはさておき。
データをまとめて扱う、データ構造の事です。

お説教臭くなりますが、お許しください。

数字とか文字列の羅列、たくさんありますよね？
  |Section|Title|
  |:--|:--------|
  |1|OverView|
  |2|まずは解説|
  |3|本日のチートシート|

これ、僕の記事の章立てです。
でも、この組み合わせ、どう管理しましょうか？

[1,"OverView",2,"まずは解説",3,"本日のチートシート"]

を、なんかそれっぽいですね。
今、あなたは、無意識に「section, titleの順でデータが並んでいる」と言う「解釈」をしてくれたのです。
ええ、忖度でもいいですよ。

ところが、赤の他人にいきなり、上のLISTを見せると、
「[]で括られてるから、一行かな？おそらく番号だね。二つ目の文字列は…おそらくタイトル？」
と言う感じで、元のテーブルを想像してくれる保証はないです。

では、どう他人やプログラムに解釈を伝えようか？と言うお話です。
なので、複数のコレクションが出てくるので、ゆっくりお愉しみください。

…いや、俺、さっぱりわかんねーので、数ヶ月LISPの本読んで…LISPのコンパイラ作る本でやっと理解したｗ

# 2. まずは解説
## 2.1 LISTその１

まずはlist、根源ですね、のぞき込むとあっちからのぞき込んでる奴。

LISTは、[]で括られ、各要素を, 区切ります。
そう、これ

  [1,"OverView",2,"まずは解説",3,"本日のチートシート"]


Elixir Schoolによれば
```
リストは値の単純なコレクションで、複数の型を含むことができます。また、一意ではない値を含むことができます:
```
だそうです。
「一意ではない値を含むことが出来ます」
ここに注目して下さい…いや、注目しなくても、僕が粘着します。すっごく。

まずは例題をやりながら、進めましょう。

```
iex(30)> [3.14, :pie, "Apple", 3.14]
[3.14, :pie, "Apple", 3.14]
```

ちょっと、例を変えております、3.14が繰り返されてる。
この順番自体は不変ですので、1番目と4番目が区別がつかなくなることはないです。
以下、後ろに追加してみました。

```
iex(30)> [3.14, :pie, "Apple", 3.14, :cake, "berry"]
```

他の本の受け売りなのですが、リストの並びは人間（またはプログラム、プログラマ）が解釈するので
あって、リストはリストでしかないそうで。


このリストの連結も出来ます。
```
iex(24)> [3.14, :pie, "Apple"] ++ [3.14, :cake, "berry"]
[3.14, :pie, "Apple", 3.14, :cake, "berry"]
```


さて、今度はリストの減算。
マッチしたものが、削除されます。

```
iex(25)> [3.14, :pie, "Apple"] -- [3.14, :cake, "berry"]
[:pie, "Apple"]
iex(26)> [3.14, 3.14, :pie, "Apple"] -- [3.14, :cake, "berry"]
[3.14, :pie, "Apple"]
```

二つの目の例、3.14が繰り返されてますが、減算では、最初にマッチしたものだけが削除されてる
ことに注意してください。

## 2.2 LISTその2

先ほどの「一位ではない値を含む」にこだわってみましょう。
では、LISTの一部を取り出すのに、どうしようか？と言う話となります。

まずは、簡単な方からやります。

解説の都合上、両方取り上げますが、2.2.2は「ああ、こいつの自己満足だな」くらいに読み飛ばしてください。
基本なんで絶対に書きたかったんですが「なんでこれ使うの？」と言うのが後からわかる仕組みなので、今、
すぐに理解しろと言うブツではないのです。

### 2.2.1 インデックスを使った、要素の取り出し

まずは、このLIST、
 [3.14, 3.99, :pie, "Apple"] 
 
 一つ一つの要素には、番号が振られているので、そいつを利用して、取り出せます。
```
iex(46)> Enum.at([3.14, 3.99, :pie, "Apple"],0)
3.14
iex(47)> Enum.at([3.14, 3.99, :pie, "Apple"],1)
3.99
iex(48)> Enum.at([3.14, 3.99, :pie, "Apple"],2)
:pie

```
要素は、０から始まるので、気を付けてくださいね。
ゼロオリジンと言います。


### 2.2.2 hd/tl(頭部/尾部)

リストを扱う際には、リストの頭部と尾部を利用したりします。頭部はそのリストの最初の要素で、尾部は残りの要素になります。
Elixirはこれらを扱うために、 hd と tl という2つの便利な関数を用意しています。

※これ、のちほど、再帰呼び出しと言うもので、「先頭だけ処理して、後ろの方は自分自身を呼び出して処理する」とかやるので。。。
　うん、その時にやろう。

今はhd/1とtl/2を使ってみましょう。

```
iex(34)> hd [3.14, :pie, "Apple"]
3.14
iex(35)> tl [3.14, :pie, "Apple"]
[:pie, "Apple"]
```

尾部と言いますが、残りの要素全部なのに注意してください。

hdはリストの先頭が返ってくるのだけど、tlは、その残り全部が返ってくる。
どう使うんじゃ？と思った時に、さっきの記憶がよみがえるんですね。
これ、意外と面白い仕組みで、
 hd([3.14, :pie, "Apple", 3.14, :cake, "berry"])
 ...3.14って、先頭だけみてどーすんじゃ？

 と思うわけですが、
```
iex(40)> hd([ [3.14, :pie, "Apple"], [3.14, :cake, "berry"] ])
[3.14, :pie, "Apple"]
iex(41)> tl([ [3.14, :pie, "Apple"], [3.14, :cake, "berry"]])
[[3.14, :cake, "berry"]]
```
ほら、LISTは「複数の型を含むことが出来る」ので、LISTの中にLISTが入ります。
リストはリストで入れ子出来るので、「先頭のリスト」だけ取り出せますな。
こうなると、「なんでもリストにほおりこんで、hdで取り出して処理する、tlはループなどで再度処理する
と言う仕組みが見えてきますなぁ。

文頭の例を見てみましょう。
  [1,"OverView",2,"まずは解説",3,"本日のチートシート"]
ちょっと弄って
  [[1, "OverView"], [2, "まずは解説"], [3, "本日のチートシート"]]
SectionとTitleの組み合わせで、listを作り、それをまとめてみました。
こうすれば、
```
iex(34)> hd([[1,"OverView"],[2,"まずは解説"],[3,"本日のチートシート"]])
[1, "OverView"]
```

先頭の取り出し、では、その次も
```
iex(35)> hd(tl([[1,"OverView"],[2,"まずは解説"],[3,"本日のチートシート"]]))
[2, "まずは解説"]
```

最後の奴

```
iex(38)> hd(tl(tl([[1,"OverView"],[2,"まずは解説"],[3,"本日のチートシート"]])))
[3, "本日のチートシート"]
```

…わけわからんですね。Elixっらしく、パイプでやります。
うん。後でパイプも説明するけど、使わんと訳が分からんままなので、許してね。

```
iex(40)> tl([[1,"OverView"],[2,"まずは解説"],[3,"本日のチートシート"]]) |> tl() |> hd()
[3, "本日のチートシート"]
```

dbg関数で、動きを確認してみましょう

```
iex(41)> tl([[1,"OverView"],[2,"まずは解説"],[3,"本日のチートシート"]]) |> tl() |> hd() |> dbg()
[iex:41: (file)]
tl([[1, "OverView"], [2, "まずは解説"], [3, "本日のチートシート"]]) #=> [[2, "まずは解説"], [3, "本日のチートシート"]]
|> tl() #=> [[3, "本日のチートシート"]]
|> hd() #=> [3, "本日のチートシート"]

[3, "本日のチートシート"]
```
…と、くどくどやってますが、これ、理解すると楽になるので、まぁ、許してください。

# 3. 本日のチートシート

  |説明|例|
  |:--------------------------------------|:--------|
  |LISTは、[]で括られ、各要素を, 区切ります。|[1, "OverView"]|
  |LISTの各要素は、それぞれ振られた番号(index)でアクセス出来ます。<br>Enum.at/2を使います<br>Indexは0から始まるので、注意してください|iex(63)> Enum.at([1, 2, 3, 4],3)<br>4<br>iex(64)> Enum.at([1, 2, 3, 4],1)<br>2<br>iex(65)> Enum.at([1, 2, 3, 4],0)<br>1|
  |LISTの先頭はhd/1で取り出せます。|iex(66)> hd([1,2,3])<br>1|
  |LISTの先頭以外の残りはtl/1で取り出せます。|iex(67)> tl([1,2,3])<br>[2, 3]|

  ...これだけ？これだけで一日？うわぁ、先を考えるとお辛いな。
  アドベンドカレンダーどころか、アドベンド四半期にならない？