okuzawatsの日記

Android / Kotlin Enthusiast 🤖

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

  1. 黒田勉、(2021)、Elixir実践ガイド、インプレス
  2. 大澤文孝、浅居尚、(2020)、docker 基礎からのコンテナ構築、日経BP
  3. Install Docker Engine on Ubuntu、retrieved from https://docs.docker.com/engine/install/ubuntu/(最終アクセス日:2022年5月23日)
  4. Docker Composeのインストール、retrieved from https://docs.docker.jp/compose/install.html(最終アクセス日:2022年5月23日)
  5. Enum#map、retrieved from https://hexdocs.pm/elixir/1.12/Enum.html#map/2(最終アクセス日:2022年5月23日)
  6. Enum#puts、retrieved from https://hexdocs.pm/elixir/IO.html#puts/2(最終アクセス日:2022年5月23日)

#Elixir

About me 😎

profile

茨城県つくば市在住のソフトウェアエンジニアです。専門領域はAndroidアプリ開発で、特にアーキテクチャに興味があります。某社でAndroidアプリ開発のテックリードをしています。

Jetpack ComposeによるAndroid MVVMアーキテクチャ入門の著者です。

👉 もっと詳しく

Writing 📝

Android MVVMアーキテクチャ入門

Androidアプリ開発の初学者に向けた、MVVM(Model-View-ViewModel)アーキテクチャの入門書を書きました。初学者の方を確実にネクストレベルに引き上げる技術書です。

👉 もっと詳しく