ElixirでFizzBuzzを書いてみた
Elixir で FizzBuzz を書いてみました。人生の中で今まで書いた FizzBuzz の中では一番苦労しましたが、学びの多い、良い FizzBuzz が書けたと思います。メモ代わりにいろいろ書き留めておきます。当方 Elixir 初心者につき理解が怪しいところがあると思いますので、その点はご容赦ください。
環境構築
「Elixir 実践ガイド」(黒田(2021))を参考に Elixir の環境構築を行いました。本書は環境構築に Docker / Docker Compose を用いていますので、本書と Docker のドキュメントを参考に、Docker を用いて環境を構築しました。Docker にはそれほど慣れておりませんでしたが、持ち前のガッツと明るさで乗り切りました。
FizzBuzz モジュール
以下の FizzBuzz モジュールに FizzBuzz を返す関数 fb
を実装します。
defmodule FizzBuzz do
@moduledoc """
Module to run FizzBuzz.
"""
@doc """
returns "FizzBuzz" if `n` is divisible by both three and five,
returns "Fizz" if `n` is divisible by three,
returns "Buzz" if `n` is divisible by five,
else returns `n`.
"""
def fb(n) when rem(n, 15) == 0, do: "FizzBuzz"
def fb(n) when rem(n, 3) == 0, do: "Fizz"
def fb(n) when rem(n, 5) == 0, do: "Buzz"
def fb(n), do: n
end
defmodule
でモジュールを定義しています。 @moduledoc
、 @doc
はモジュール属性です。Elixir におけるドキュメンテーションコメントといったところでしょうか。今回のコードでは活用できていませんが、Markdown で書けます。
肝心の処理は、関数 fb
の引数に対するパターンマッチングで FizzBuzz を返しています。関数については
def fb(n) do
# TODO
end
のような形式でも書くことができますが、いわゆるキーワード形式と呼ばれる、上記のような( , do: "FizzBuzz"
)書き方もできます。詳しくは黒田(2021) p.121 を参照してください。
パイプ演算子
上記 FizzBuzz モジュールの fb
関数を用いて、FizzBuzz を標準出力に出力します。Elixir らしく(要出典)、パイプ演算子を用います。
(1..100)
|> Enum.map(&FizzBuzz.fb/1)
|> Enum.each(&IO.puts(&1))
Elixir の Enum#map 関数は、enumerable と fun の 2 つの引数をとります(参考文献 5)。それにも関わらず、上記のコードの 2 行目では引数を 1 つしか受け取っていません。パイプ演算子の右側に置かれた関数は、第 1 引数をパイプ演算子の左側の式から受け取ります。そのため、2 行目では enumerable として Range 構造体 1..100
を受け取っています。
1..100
を受け取った Enum#map 関数は、 1..100
のそれぞれについて FizzBuzz#fb を呼び出します。ここで、 &FizzBuzz.fb/1
の &
は、名前付き関数を関数型の 項(term) として取り出す キャプチャ演算子 です。ここでの処理は、FizzBuzz#fb 関数を引数として渡している、ということです。また &FizzBuzz.fb/1
の /1
は引数の個数を表す アリティ(arity) です。ここでは、引数の数が 1
の関数であることを表しています。
FizzBuzz#fb の評価結果をさらにパイプ演算子の右項に渡しています。ここはちょっと説明を誤魔化しますが、enumerable のそれぞれの項を引数として IO#puts を呼び出しています。
これで FizzBuzz ができました。FizzBuzz をするだけで一苦労でしたが、とてもきれいなコードが書けたのではないかと思います。もうしばらく、Elixir と戯れてみたいです。
GitHub のリポジトリ
GitHub のリポジトリとしてソースコードを公開しました。
Reference
- 黒田勉、(2021)、Elixir 実践ガイド、インプレス
- 大澤文孝、浅居尚、(2020)、docker 基礎からのコンテナ構築、日経 BP
- Install Docker Engine on Ubuntu、retrieved from https://docs.docker.com/engine/install/ubuntu/(最終アクセス日:2022年5月23日)
- Docker Compose のインストール、retrieved from https://docs.docker.jp/compose/install.html(最終アクセス日:2022年5月23日)
- Enum#map、retrieved from https://hexdocs.pm/elixir/1.12/Enum.html#map/2(最終アクセス日:2022年5月23日)
- Enum#puts、retrieved from https://hexdocs.pm/elixir/IO.html#puts/2(最終アクセス日:2022年5月23日)
Discussion