(この記事は、「Elixir Advent Calendar 2019」の3日目です)
昨日はzacky1972先生の「Elixir Zen スタイル講座: ループを Enum.reduce/3 で表す方法」です!こちらもぜひぜひ!
はじめに
- 12/3を担当します
- 12/3の窓をあけてみましょう
作品
lib/advent_calendar.exs
defmodule AdventCalendar do
def open([1, 2, 3] = list) do
Enum.join(list, "、") <> "ダー!!!"
end
def open(["一", "二", "三"] = list) do
"加藤" <> Enum.join(list) <> "先生"
end
def open(123 = num) do
Integer.to_string(num) <> "ダー!!!"
end
def open("一二三") do
"ひふみん"
end
def open(_) do
nil
end
def december_3_window do
windows() |> Enum.random()
end
defp windows do
[[1, 2, 3], ["一", "二", "三"], 123, "一二三", ""]
end
end
実行結果例
$ iex
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c "lib/advent_calendar.exs"
[AdventCalendar]
iex(2)> AdventCalendar.december_3_window |> AdventCalendar.open
nil
iex(3)> AdventCalendar.december_3_window |> AdventCalendar.open
"1、2、3ダー!!!"
iex(4)> AdventCalendar.december_3_window |> AdventCalendar.open
"加藤一二三先生"
iex(5)> AdventCalendar.december_3_window |> AdventCalendar.open
"123ダー!!!"
iex(6)> AdventCalendar.december_3_window |> AdventCalendar.open
"ひふみん"
iex(7)> AdventCalendar.december_3_window |> AdventCalendar.open
"123ダー!!!"
iex(8)> AdventCalendar.december_3_window |> AdventCalendar.open
"ひふみん"
iex(9)> AdventCalendar.december_3_window |> AdventCalendar.open
nil
iex(10)> AdventCalendar.december_3_window |> AdventCalendar.open
"1、2、3ダー!!!"
解説という名でElixir愛を語る
- AdventCalendar.openを5種類定義しています
- Elixirのパターンマッチングという機構で適切な関数が呼び出されます
-
|>
はパイプ演算子と呼ばれています- 実行結果が次の関数の第一引数にはいります
- この記事の例ではあまりよさが伝わらないとおもいますが、たとえばHTTP Getしてbodyを取り出して、JSONをキーでアクセスできるようにして、所望のキーの値だけとりだしたいみたいなときにきれいにかけます
- 私の記事ですが、以下の例なんかが良さがつたわるんじゃないかとおもっております
- ElixirでSlackの絵文字(emoji)を一括エクスポート
- Nervesを使ってRaspberry pi2からTwitterの投稿を行う
- I Was Born To Love Elixir!!!
- We are the Alchemists, my friends!!!
メッセージ
- iexに貼ってお楽しみください。
[73, 116, 32, 105, 115, 32, 110, 101, 118, 101, 114, 32, 116, 111, 111, 32, 108,
97, 116, 101, 32, 8211, 32, 110, 101, 118, 101, 114, 32, 116, 111, 111, 32,
108, 97, 116, 101, 32, 116, 111, 32, 115, 116, 97, 114, 116, 32, 111, 118, 101,
114, 44, 32, 110, 101, 118, 101, 114, 32, 116, 111, 111, 32, 108, 97, 116, 101,
32, 116, 111, 32, 98, 101, 32, 104, 97, 112, 112, 121, 46] |> IO.puts
[12371, 12398, 36947, 12434, 34892, 12369, 12400, 32, 12393, 12358, 12394,
12427, 12418, 12398, 12363, 32, 21361, 12406, 12416, 12394, 12363, 12428, 32,
21361, 12406, 12417, 12400, 36947, 12399, 12394, 12375, 32, 36367, 12415,
20986, 12379, 12400, 32, 12381, 12398, 19968, 36275, 12364, 36947, 12392,
12394, 12426, 32, 12381, 12398, 19968, 36275, 12364, 36947, 12392, 12394,
12427, 32, 36855, 12431, 12378, 34892, 12369, 12424, 32, 34892, 12369, 12400,
20998, 12363, 12427, 12373, 32, 12354, 12426, 12364, 12392, 12358] |> IO.puts
メッセージの作り方
iex(1)> IEx.configure(inspect: [limit: :infinity]) # おまじない的に(結果を省略されないようにするため)
:ok
iex(2)> s = "文字列"
"文字列"
iex(3)> s |> String.codepoints() |> Enum.map(&(if &1 == " ", do: "?\\s", else: "?#{&1}")) |> Enum.map(&(Code.eval_string(&1))) |> Enum.map(&(elem(&1, 0)))
[25991, 23383, 21015]
- @kikuyuta先生の「言語バトル時には秘匿しておきたい Elixir の急所」にインスパイアされました
2020/7/22(水)追記
- すごくゴテゴテとした難しいことを以前は書きましたが、メッセージの作り方は以下でよいです
iex> IEx.configure(inspect: [limit: :infinity, charlists: :as_lists])
:ok
iex> "文字列" |> String.to_charlist
[25991, 23383, 21015]
参考
- https://hexdocs.pm/iex/IEx.html#configure/1-inspect
- https://hexdocs.pm/elixir/String.html#module-integer-code-points
次回
次回はim_miolabさんの「テスト駆動開発を、Elixirでゆるふわにやってみる (テスト自動化つき)」です!こちらも是非どうぞ~