LoginSignup
9
2

More than 1 year has passed since last update.

闘魂Elixir ーー Enum.reduceがあればなんでもできる!

Last updated at Posted at 2023-03-07

$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$

$\huge{闘魂とは己に打ち克つこと。}$
$\huge{そして闘いを通じて己の魂を磨いていく}$
$\huge{ことだと思います}$

はじめに

この記事は、2023/03/11(土)に行われる「【オフライン開催!】fukuoka.ex#53 Elixir Lightning Talks!!」の発表(LT)資料です。

猪木さんの有名な言葉に「元氣があればなんでもできる!」があります。
これになぞらえて、
Enum.reduceがあれば、Enumはなんでもできます」を発表します。
Elixirをはじめたばかりの方は、まずEnumモジュールに慣れるとよいです。
Enumモジュールはよく使います。

Mix.install [{:req, "~> 0.3.6"}]

"https://qiita.com/api/v2/items?query=tag:Elixir&per_page=100"
|> Req.get!()
|> Map.get(:body)
|> Enum.filter(fn %{"likes_count" => likes_count} -> likes_count > 1 end)
|> Enum.map(fn %{"title" => title, "user" => %{"id" => id}, "likes_count" => likes_count} -> {title, likes_count, id} end)

対象読者

  • Elixirをはじめてみようかとはおもっているもののなかなか最初の一歩が踏み出せずに危ぶんでいる人
  • Elixirをはじめたばかりの人

自己紹介

名乗るほどのものではございません。

Twitter

Qiita

Elixirタグのユーザーランキング第2位。

スクリーンショット 2023-03-07 21.48.54.png

受賞歴

#Qiitaアドカレ 日本マイクロソフト賞④ (2021/01/15)

Qiita Advent Calendar 2022 Qiita賞個人部門完走賞 (2023/01/23)

GitHub

Elixirへの貢献

覚えていられれるくらい数が少ないという証左です。
私の貢献

Elixir本体、Phoenix、Nerves Livebook、Ecto

執筆

闘魂Elixirコミュニティ主催

every dayもくもく会。

Elixirイベントカレンダー

スクリーンショット 2023-03-09 9.11.40.png

闘魂とは己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことだとおもいます。
ーー 他人と比べる必要はありません。自分のペースで、己の技術力を高めていきましょう!

北米、南米からの参加者もいらっしゃいます。

モットー: We are the Alchemists, my friends!!!
我々ハ錬金術師我ガ友ヨ


Elixirっぽいプログラム例

Qiita API v2を利用させていただいて、Elixirに関する記事を取得してみます。

ここでは、Dockerで動かす例を示します。

$ docker run --rm -it hexpm/elixir:1.14.3-erlang-25.2.3-ubuntu-jammy-20221130 iex

hexpm/elixirは、ElixirのWebアプリケーションフレームワークPhoenixドキュメントにもでてくる由緒正しきDockerイメージです。

上のコマンドを迷わず実行すると、IExと呼ばれるREPL(その場でプログラムを打ち込んで結果が返ってくるのを楽しめる便利な道具)が立ち上がります。
迷わず、Elixirのプログラムを打ち込んでいきます。

まず、ReqというHTTPクライアントライブラリをインストールします。

iex> Mix.install [{:req, "~> 0.3.6"}]

Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn]Shall I install rebar3? (if running non-interactively, use "mix local.rebar --force") [Yn]を訊かれたら、迷わず元氣よくYを答えてください。

"https://qiita.com/api/v2/items?query=tag:Elixir&per_page=100"
|> Req.get!()
|> Map.get(:body)
|> Enum.filter(fn %{"likes_count" => likes_count} -> likes_count > 1 end)
|> Enum.map(fn %{"title" => title, "user" => %{"id" => id}, "likes_count" => likes_count} -> {title, likes_count, id} end)

ここでみたように、Elixirでは、パイプ演算子|>Enumモジュールを使ってプログラミングすることが多いです。
上の例には、実はマップやパターンマッチなど重要な概念がぎゅっとつまっています。

上記のプログラムは、GET /api/v2/itemsで、Elixirタグがついた記事の一覧を100件取得し、いいねが1以上ついた記事でフィルタして、各要素を{タイトル, いいね数, id}に丸めています。

ここからはEnumモジュールに話をしぼります。

2023-03-08 09:21現在の実行結果です。

[
  {"闘魂Elixir ーー Enum.reduceがあればなんでもできる!", 3,
   "torifukukaiou"},
  {"Elixir Desktop で JavaScript 側をデバッグする(console.log の表示など)",
   2, "RyoWakabayashi"},
  {"Elixir Desktop iOS でカメラ撮影【2023年3月版】", 3,
   "RyoWakabayashi"},
  {"Rustler precompiledの環境構築", 4, "Shintaro_Hosoai"},
  {"Chatwork上で会話できるChatGPTボットをAWS Lambdaだけで実現するとき、Elixirだと少し良いものができたお話",
   2, "erin"},
  {"LivebookでChatGPT APIを使ってみた。試した会話から、ChatGPTお母さんは3時のおやつは無しだと判明した。",
   3, "GeekMasahiro"},
  {"Elixir 高性能な數の數え方(counters)", 5, "mnishiguchi"},
  {"Elixir ETSインメモリデータベースのバックアップと復元",
   7, "mnishiguchi"},
  {"Elixir 挑戦記 - 地理空間データを扱う", 3, "SF-28"},
  {"LivebookでKino.DataTableが表示されない", 3, "SF-28"},
  {"Elixir 学習記(4. パターンマッチング)", 3, "SF-28"},
  {"草莽Erlang ── 43. lists:concat", 2, "mnishiguchi"},
  {"草莽Erlang ── 42. lists:join", 2, "mnishiguchi"},
  {"Elixir Livebook で地図にポイントと一緒にデータを描画出来ないものだろうか",
   5, "hozyo"},
  {"Elixir Explorer データフレーム(DataFrame)の列名がクエリで使えない場合の回避方法",
   4, "RyoWakabayashi"},
  {"草莽Erlang ── 41. lists:append", 2, "mnishiguchi"},
  {"e-Stat の家計調査データから業界の成長・衰退や新型コロナの影響を可視化する",
   8, "RyoWakabayashi"},
  {"Nervesやっている人でディスク容量が少ない人は~/.nervesを消すとよいかもしれません",
   4, "torifukukaiou"},
  {"Elixir v1.17ではIO.read(:all)はDeprecateだってよ(2023-02-25現在v1.14)",
   4, "torifukukaiou"},
  {"Phoenix Storybook で楽しいコンポーネントベース開発", 7,
   "RyoWakabayashi"},
  {"Elixir Livebook で佐賀県のGTFSで全バス路線を地図に描きたいのだ",
   7, "hozyo"},
  {"Elixir Livebook を改造して3Dの立方体を回転させる 〜Kinoの旅 なんでもできる国〜",
   5, "RyoWakabayashi"},
  {"LivebookのSmartCellのDBとMapを使ってGPSログデータを可視化してみた",
   4, "the_haigo"},
  {"LivebookのSecretsを使う", 5, "SF-28"},
  {"Elixir 挑戦記 - 開発環境構築", 4, "SF-28"},
  {"Petal Pro を Fly.io にデプロイして超簡単 Web アプリケーション公開",
   8, "RyoWakabayashi"},
  {"UbuntuコンテナでEXLAが動かない", 4, "SF-28"},
  {"Petal Pro で爆速高機能 Web 開発を体験してみた", 10,
   "RyoWakabayashi"},
  {"総務省統計局の家計調査データからチョコレートを分析する",
   6, "RyoWakabayashi"},
  {"総務省統計局の家計調査データを Livebook で取得、加工、分析する",
   4, "RyoWakabayashi"},
  {"Elixir Livebook で佐賀県のGTFSからバス停を地図に落とせたらいいなー",
   9, "hozyo"},
  {"競プロ未経験者が、Elixir、LivebookでAtCoderに初参加してみたらアウトプットの機会として良かった話",
   6, "GeekMasahiro"},
  {"paiza.ioでelixir その185", 2, "ohisama@github"},
  {"paiza.ioでelixir その184", 2, "ohisama@github"},
  {"mix testでNGが発生したテストをseed値を指定して再現する方法",
   5, "GeekMasahiro"},
  {"逆にStreamを使う例題を作ってみよう!", 5, "GeekMasahiro"},
  {"Elixir 挑戦記 - 衛星データからNDVI算出", 8, "SF-28"},
  {"Elixir Livebook で Algolia からデータ検索してみる", 5,
   "RyoWakabayashi"},
  {"*Interp移植録 - 単眼視深度推定 / HR-Depth (OnnxInterp)", 4,
   "ShozF"},
  {"Google Colaboratory 上で Elixir Bumblebee を動かし、画像生成やテキスト補完を実行する",
   7, "RyoWakabayashi"},
  {"Google Colaboratory 上で Elixir Nx の各種バックエンドを動かす",
   4, "RyoWakabayashi"},
  {"「ElixirImp#28:Elixir Advent CalendarコラムをLT化しましょ!」レポート(2023-02-15)",
   13, "torifukukaiou"},
  {"ElixirのStreamを使ってみる", 4, "GeekMasahiro"},
  {"Elixir 学習記", 4, "SF-28"},
  {"Elixir 学習記(3. 演算子)", 7, "SF-28"},
  {"evision で検出した顔に Elixir Image でモザイクをかける", 5,
   "RyoWakabayashi"},
  {"Elixir Image と Nx と evision で相互変換", 3, "RyoWakabayashi"},
  {"Elixir Image で SVG を PNG に変換する", 3, ...},
  {"長年break文を使い続けたプログラマーが、break文の無いElixirを学んで、遅延評価にたどり着いた話",
   ...},
  {...},
  ...
]

Enumモジュール

Enumモジュールは、リストやマップ、キーワードリストなどenumerablesと呼ばれるデータを取り扱う関数がそろっています。

最重要関数を4つ紹介します。
独断と偏見です。私の主観です。

Enum.map/2

enumerables(リストなど)の要素一つひとつに関数を適用して、もとのenumerablesと同じ長さのenumerablesを作ります。
例を示します。[1, 2, 3]のリストの各要素に+1します。

iex> Enum.map([1, 2, 3], fn x -> x + 1 end)
[2, 3, 4]

Enum.filter/2

enumerables(リストなど)の要素一つひとつに関数を適用して、Truthyとなる要素のみからなるenumerablesを作ります。
例を示します。[1, 2, 3]のリストの中から偶数のみの要素でフィルターします。

iex> Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[2]

Enum.max/3

enumerables(リストなど)の中から一番大きな値を返してくれます。
一番簡単な要素が整数のリストから最大値を取得する例を示します。

iex> Enum.max([1, 2, 3])
3

Enum.reduce/3

専門家の間では畳込みと呼ばれています。
これがわかれば、あなたも専門家です。

よく示される例は足し算です。

Enum.reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6

けれどこれって初見ではなかなか理解するのは難しいかもしれません。
私の主観にすぎません。
もちろん、初見でもわかるぜーっていう方はいるとおもいます。すごいことです! あなたは、関数型言語のセンス抜群です。センスの塊です。

どういうふうに計算が進んでいるのかというと以下の感じ(猪木寛至)です。

x = 1, acc = 0 -> 1 + 0 = 1
x = 2, acc = 1 -> 2 + 1 = 3
x = 3, acc = 3 -> 3 + 3 = 6

これを理解するにはどうしたらいいかというと、さきほど紹介した3つの関数、つまりEnum.map/2Enum.filter/2Enum.max/3Enum.reduce/3でわざわざ書いてみるとよく理解できます。

以下、さきほど紹介したプログラム例をEnum.reduce/3で書いてみます。

map相当

[1, 2, 3]のリストの各要素に+1します。

iex> Enum.reduce([1, 2, 3], [], fn x, acc -> acc ++ [x + 1] end)
[2, 3, 4]

どういうふうに計算が進んでいるのかというと以下の感じ(猪木寛至)です。

x = 1, acc = [] -> [] ++ [2] = [2]
x = 2, acc = [2] -> [2] ++ [3] = [2, 3]
x = 3, acc = [2, 3] -> [2, 3] ++ [4] = [2, 3, 4]

Enum.map/2の使用例を再掲。

iex> Enum.map([1, 2, 3], fn x -> x + 1 end)
[2, 3, 4]

filter相当

[1, 2, 3]のリストの中から偶数のみの要素でフィルターします。

iex> Enum.reduce([1, 2, 3], [], fn 
  x, acc when rem(x, 2) == 0 -> acc ++ [x]
  _, acc -> acc
end)
[2]

どういうふうに計算が進んでいるのかというと以下の感じ(猪木寛至)です。

x = 1, acc = [] -> []
x = 2, acc = [] -> [] ++ [2] = [2]
x = 3, acc = [2] -> [2]

Enum.filter/2の使用例を再掲。

iex> Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[2]

max相当

要素が整数のリストから最大値を取得する例を示します。

iex> Enum.reduce([1, 2, 3], 0, fn 
  x, acc when x > acc -> x
  _, acc -> acc
end)
3

どういうふうに計算が進んでいるのかというと以下の感じ(猪木寛至)です。

x = 1, acc = 0 -> 1
x = 2, acc = 1 -> 2
x = 3, acc = 2 -> 3

Enum.max/3の使用例を再掲。

iex> Enum.max([1, 2, 3])
3

まとめます。
この記事で言いたいことをもう一度おさらいします。
猪木さんの有名な言葉に「元氣があればなんでもできる!」があります。
これになぞらえて、
Enum.reduceがあれば、Enumはなんでもできます」を発表しました。

根拠は、Enumerableプロトコルの中核関数は、Enumerable.reduce/3です。


おまけ

時間が余るようだったらちょっとみせます。
たぶん、話が脱線して、おまけは紹介できないとおもいます。

エリクサーチ

もっとElixirを楽しんでみようというかたへの道しるべ。

image.png

ANSIエスケープコード

闘魂プログラミング

猪木さんの試合など

燃える闘魂 といえば、アントニオ猪木さんです。

猪木さんのことを懐かしく思い出す方もいらっしゃるでしょうし、猪木さんが試合をしている姿を知らない方もいらっしゃるでしょう。
猪木さんの試合動画などをご紹介します。
2023-03-11現在、新日本プロレスワールドで無料公開されています。

(ちょっと前までは、ドン・フライとの引退試合やハルク・ホーガン戦などいくつか無料でしたが、今朝みたら有料コンテンツに変わっていました。私はもちろん有料会員です)


さいごに

まとめます。
この記事で言いたいことをもう一度おさらいします。
猪木さんの有名な言葉に「元氣があればなんでもできる!」があります。
これになぞらえて、
Enum.reduceがあれば、Enumはなんでもできます」を発表しました。

根拠は、Enumerableプロトコルの中核関数は、Enumerable.reduce/3だからです。

Elixirをはじめてみようかとはおもっているもののなかなか最初の一歩が踏み出せずに危ぶんでいる人へ

闘魂Elixirコミュニティ、elixir.jp SlackDiscordサーバー『elixirと見習い錬金術師』はあなたの訪れを熱烈歓迎します。

この道を行けば
どうなるものか
危ぶむなけれ
危ぶめば道はなし
踏み出せば
その一足が道となり
その一足が道となる
迷わず行けよ
行けばわ(分)かるさ
ありがとうーーーーッ!!!


闘魂とは、 「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」 との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。


$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{1、2、3 ぁっダァー!}$

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2