自衛官からエンジニアへ Elixirから始める Web開発 Part12

この記事は「Elixir Advent Calendar 2023」12日目の記事です
東京にいるけどfukuokaexのYOSUKEです。

普段は 合同会社TheWaggle で教材開発・システム開発・研修講師などマルチに活動してます。

このシリーズでは、文系ですらない、体育会系でも始められるプログラミング学習　というテーマで元自衛官だった僕が
自衛官からエンジニアになってもらいたいという気持ちを込めて、普段は大人しいですが、このコラムシリーズでは、あえて、体育会系のノリで、貴様ら理屈で覚えるなら体で覚えろ！というノリで書いてみたいと思います。

なので、初学者向けですが、理論は後回し、まずは動かして体感しろってノリの第12回目です。

それでは、いくぞ！

## Enumを制すものはリストを制す！

よーし、次回は「貴様らの班員 10名全員に一気にそれぞれ、銃を受け渡す方法を伝授しよう！」と言い続けて、3話も引っ張ってしまったが、それは貴様らのせいだ！　貴様らが無知がゆえ、先に教えなければならないことがたまりに溜まって、ここまで引っ張らざるえなかったのだ。

* えー、そんな言いがかりな！

何？　貴様、上官に向かって口答えをするのか！　その場に腕立て伏せの用意！

* イッチ、二！

いいか、貴様ら、戦場は理不尽の塊だ！ここでは、理不尽にも対応する精神が必要だ！
そして、開発の現場も上官の理不尽が横行していると聞く！貴様らはそんな理不尽に負けないように訓練しているのだ。
わかったか！

* はい！

よーし、いいだろう。それでは、腕立て伏せ 100回だ！

* イーチ、ニー、サーん、、、、、九十九、

貴様、その九十九の声はなんだ！気合いが足りない！　最初からだ！

* イーチ、ニー、サーん、、、、、九十九

九十九てんいち！（教官の声）
九十九てんに！（教官の声）

* 九十九てんさーん！
* 九十九てんしー！
* 九十九てんご〜！
* 九十九てんろく！
* 九十九てんなな！
* 九十九てんはち！
* 九十九てんきゅう
* ひゃーく！

よし、いいだろう。貴様ら、100回の腕立て何て簡単だろう？(実際は210回やらされてる）だが、同じことを繰り返し100回、1000回、10000回とするのは苦痛だろう。そんな繰り返し同じことをしなければならない苦痛から解放してくれる道具があったらどうする？

貴様らにはそんな夢のような道具を今日は紹介してやろう。そして、それを使って、いよいよ、「貴様らの班員 10名全員に一気にそれぞれ、銃を受け渡す方法を伝授しよう！」を実現しよう。

まず、前回までに覚えたListだが、おさらいだ。もう一度、実行してみよう。

```elixir
list = Tuple.to_list({ "松浦", "橋本", "鈴木", "後藤", "伊藤", "薪", "空", "峰", "桂", "早乙女" })
["松浦", "橋本", "鈴木", "後藤", "伊藤", "薪", "空", "峰", "桂", "早乙女"]
 ```

この一人ずつの名前と武器を以下のように一つのデータにしたいわけだ。

 ```elixir
 {"松浦", %{ 
    "名称" => "20式5.56mm小銃" ,
    "種類" => "小銃" ,
    "製造国" =>  "日本" ,
    "口径" =>	"5.56 mm" ,
    "銃身長" => "330 mm" ,
    "使用弾薬" =>	"89式5.56mm普通弾" , 
    "装弾数" => "30発" ,
    "作動方式" => "ガス圧作動方式" ,
    "全長" =>	"851 mm (銃床最小 779 mm)" ,
    "重量" => "3.5 kg" ,
    "発射速度" =>	"650 – 850発/分" ,
    "有効射程" =>	"500 m以上"
   }
}
```

要するに、名前と装備のタプルの形にし、装備の中に20式のマップデータが入れば良いわけだ。

```elixir
{name, soubi}
```

そうすると、大量に作る```{name, soubi}```この形のデータはnameが人毎に変わるが、```soubi```の部分は同じ20式の固定で良いことになる。では、まずは```soubi```に20式をマッチさせよう。

```elixir
soubi = %{ 
    "名称" => "20式5.56mm小銃" ,
    "種類" => "小銃" ,
    "製造国" =>  "日本" ,
    "口径" =>	"5.56 mm" ,
    "銃身長" => "330 mm" ,
    "使用弾薬" =>	"89式5.56mm普通弾" , 
    "装弾数" => "30発" ,
    "作動方式" => "ガス圧作動方式" ,
    "全長" =>	"851 mm (銃床最小 779 mm)" ,
    "重量" => "3.5 kg" ,
    "発射速度" =>	"650 – 850発/分" ,
    "有効射程" =>	"500 m以上"
   }
```

よーし、これで準備は完了だ、今、`lsit` の中には```["松浦", "橋本", "鈴木", "後藤", "伊藤", "薪", "空", "峰", "桂", "早乙女"]```この名前の値が入ったリストのデータがある。そして、`soubi` の中には20式のデータがある後は、この`list`の中の名前を一つずつ```{name, soubi}```の名前の部分に入れていくだけだ。

そこで、便利な道具が```Enum```モジュールの```map```関数だ。まずは、前回覚えたリファレンスの読み方で使い方を読んでこい！

https://hexdocs.pm/elixir/1.15.7/Enum.html#map/2

よーし、読んできたか！
何？ 読んできたが何を言っているのかさっぱりわからない？　
そうかそうか、貴様ら程度の脳みそでは理解できまい！（教官も昔理解できなかったから、内心ほっとしてるようす）

よーし、頭の弱い貴様らに！　特別にわかりやすく解説してやろう！　ありがたく思え！
まず、今回簡単に装備を配布する方法の答えは以下の通りだ！　

```elixir
Enum.map(list, &{&1, soubi})
```
まずは、```Enum.map(1番目,2番目)```には1番目に入れる値と2番目に入れる値、要するに２つの値を入れる必要がある。
そして、1番目に入れる値は```リスト```だと思え、リファレンスの解説には```enumerable```と書かれていたが、貴様らが理解するにはまだ早い！　今のところは、```リスト```を入れるものと覚えておけ！

そして、2番目には```fun```と書かれていたが、これも貴様らにはまだ理解できないので無視しろ！今のところは、```&```この記号を使ったら便利になる方法を教えるからそれだけ覚えろ！

2番目に入れるものは`&`を使った右側には必要なデータの形をおき、そしてそのデータの中に&1をおくことでリストの値を順番に一つずつ当てはめることができる。そう言うルールだと思え！

今回の場合なら、```["松浦", "橋本", "鈴木", "後藤", "伊藤", "薪", "空", "峰", "桂", "早乙女"]```最初に```"松浦"```が&1に入ってくる。そして、次に```"橋本"```が&1に入ってくる。この繰り返しが行われている。

実行したら以下のようになる。

```elixir
[
  {"松浦",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"橋本",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"鈴木",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"後藤",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"伊藤",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"薪",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"空",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"峰",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"桂",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }},
  {"早乙女",
   %{
     "作動方式" => "ガス圧作動方式",
     "使用弾薬" => "89式5.56mm普通弾",
     "全長" => "851 mm (銃床最小 779 mm)",
     "口径" => "5.56 mm",
     "名称" => "20式5.56mm小銃",
     "有効射程" => "500 m以上",
     "発射速度" => "650 – 850発/分",
     "種類" => "小銃",
     "装弾数" => "30発",
     "製造国" => "日本",
     "重量" => "3.5 kg",
     "銃身長" => "330 mm"
   }}
]
```

この`&`はどんな形でも利用できる。今回はタプルにしたが、当然、リストでもマップでも、そして何もない場合でも使える。
気になるなら手元で試してみろ！

```elixir
Enum.map(list, &[&1, soubi])
Enum.map(list, &%{&1 => soubi})
```

そして、何もない場合、結果は元のデータの形と同じだ。
```elixir
Enum.map(list,& &1)
["松浦", "橋本", "鈴木", "後藤", "伊藤", "薪", "空", "峰", "桂", "早乙女"]
```

上記を使って、貴様らの班員に階級をつけてみよう。 ```<>``` 文字列を連結する道具を使って階級を追加してみせよう。

```elixir
Enum.map(list,& &1<>"2士")
["松浦2士", "橋本2士", "鈴木2士", "後藤2士", "伊藤2士", "薪2士", "空2士", "峰2士", "桂2士", "早乙女2士"]
```

よし、それでは次回はこの2番目に入れる```fun```について解説してやろう。しかし、```fun```の解説はまた数回にわたるから覚悟しろ！　今日はここまで、それでは次回 Part13でまた会おう！