ITエンジニアのための勉強会・イベントレポート情報メディア

勉強会に行ってみた!第44回「最新技術キャッチアップ勉強会(Elixir編)」
event

勉強会に行ってみた!第44回
「最新技術キャッチアップ勉強会(Elixir編)」

2016.12.05

いま注目の言語、Elixirの勉強会です。FizzBuzz問題をいろんな方法で解くことで、Elixirに慣れようという趣旨のようです。でもなんでFizzBuzzなんでしょうか?勉強会を覗いてきました。

三土たつお

今回の会場は、五反田のfreee株式会社でした。

freeeといえばクラウド会計ソフトの会社ですね。ただ、勉強会の主催というわけではなく、今回はスポンサーとして会場を提供していました。

左から、freeeの森さん、講師の城門さん、主催のPLANISTAの獅々見さん。

今回の勉強会を主催する獅々見さんは、東京大学の4年生のときにPLANISTAを起業して、いまも在学中です。そして講師の城門さんも東京大学の3年生です。

そして今回の勉強会は学生限定でした。みんな都内の大学生です。つまり、主催者も講師も参加者もみんな学生なんです。素晴らしくないですか?

先生も生徒もみんな学生ってところが、自主的な学びの場っていう感じですごくいいなと思いました。しかも学ぶ内容も Elixir という若い言語です。なんていうか、植物の先端にある成長点のような場所だなと思いました。

最初に、参加者の自己紹介がありました。

東京大学、慶応大学、東京海洋大学などの学生が来ているようでした。学年は1年生から4年生まで。プログラムの経験もほとんどない人から普段からやってる人までさまざまでした。

ところで FizzBuzz ってなんだ

FizzBuzz は知っている人も多いとは思いますが、最初にちゃんと説明がありました。以下のルールに従って文字列を出力する問題です。

1〜100の数について、
・3の倍数のときは “Fizz”
・5の倍数のときは “Buzz”
・15の倍数のときは “FizzBuzz”
・その他のときは、その数字をそのまま

つまり、最初のいくつかについてやってみると

1
2
Fizz
4
Buzz
6
7

のようになります。

これをただ解くだけなら、if文と余りの計算が書ければまあできるんですが、解き方そのものを工夫したり、言語ごとの特徴を使うことで、いろんな書き方ができるというのが FizzBuzzの面白さだと思います。

Elixirの基礎について

FizzBuzz問題を解くにあたって、まずはElixirの最低限の基礎についてのお話がありました。

Elixirとは、一言でいえば Erlang を Rubyっぽくしたものとのこと。

Erlang は、並行処理が得意だったりしていい言語なんですが、文法が独特だったりしてとっつきにくいんですよね。それを解決したのが Elixir です。

Elixirにあるパターンマッチ、無名関数の定義、リストなどの特徴については、実際に FizzBuzzを学びましょう、ということになりました。

無名関数とパターンマッチ

x = fn
 (1, 3) -> 4
 (_, 2) -> 3
 (1, _) -> 2
 (_, _) -> 1
end

IO.puts(x.(1,3))

これは Elixir のコード片です。意味としては、まず fn から end までで無名関数を定義し、それを x としています。つぎに IO.puts() で、xに(1,3)を適用した結果を出力しています。

無名関数の中で使っているのがパターンマッチですね。一行目は、引数が 1,3 なら 4を返すという意味。そうでなければ二行目に行って、引数の1番目はなんでもよくて、2番目が2なら3を返す、のように続きます。

この場合は 1,3 を適用していますので、最初のパターンがマッチして 4 が返ります。

剰余と繰り返し

ある数を割ったあまりのことを剰余といいますが、Elixir では

rem(n,3)

のように表します。これは n を 3で割ったあまりですね。これが 0 なら Fizz と出力したい。

次は繰り返しです。たとえば、1から10までの数をただ出力するコードは次のとおりです。

Enum.map(1..10, fn n -> IO.puts n end)

なんとなく分かりますよね。1..10 でその範囲をつくり、続く無名関数でただ n の値を出力しています。あとはここの無名関数の中身を、FizzBuzz に沿った内容にすればOKです。

最初のFizzBuzzの解

ここまでやった内容を組み合わせればもうFizzBuzzが解けます。次のとおりです。

checkFizzBuzz = fn
 (_,0,0) -> “FizzBuzz”
 (_,0,_) -> “Fizz”
 (_,_,0) -> “Buzz”
 (n,_,_) -> n
 end

fizzBuzz = fn
 n -> checkFizzBuzz.(n, rem(n,3), rem(n,5))
 end

printFizzBuzz = fn
 n -> IO.puts fizzBuzz.(n)
 end

Enum.map(1..100, printFizzBuzz)

最初の checkFizzBuzz は、最初の引数が n、2番目がnを3で割ったあまり、3番目がnを5で割ったあまりです。パターンマッチを使って、nを5で割ったあまりが0のときは “Buzz” を返すといったようになってます。

fizzBuzzは、checkFizzBuzz を使って、nに対する FizzBuzzの結果を調べます。printFizzBuzzは単にそれを出力してるだけです。

最後に Enum.map でまとめて出力すれば、できあがりというわけ。

プログラミングに慣れていないと言っていた学生も、アドバイスをもらいながら最終的な答えまでたどり着いていました。

FizzBuzzの別の解き方

FizzBuzzには解き方が無数にある、というわけで城門さんはElixirでの別の解き方も紹介していました。

その別の解き方を理解するためには、iex と Char lists の話が必要になります。Elixir にはインタラクティブな実行環境があり、それが iex です。たとえばさっきの剰余の rem を試したければ、コマンドラインから iex と打って、

iex(1)> rem(8,3)
2

のようにすれば、8を3で割ったあまりは2、みたいなことが分かります。
じゃあ次はリストを試そう、と思って次のように打ってみます。

iex(1)> [48,49,50]
’012’

なんと、結果が ‘012’ になりました。48, 49, 50 のリストなのに?
これが Char lists というやつです。Elixirでは、ASCIIコードと見なすことができる数のリストは、文字のリストとして解釈しちゃうんだそうです。なんだその機能。でとにかく 48 はASCIIコードで ‘0’ という文字を意味するので、上記のようになると。

で、この妙な機能を使うと FizzBuzz を次のように解くことができます。

調べたい数が 75 だとしたら、これを一回 CharList に変換して ‘7’ と ‘5’ に分けます。つぎに 7 と 5 を足して12を得ます。12をさらに ‘1’ と ‘2’ に分けて足すと最終的に3になります。この最終的な数が3で割り切れればもともとの数も3で割れるという性質がありますから、これで Fizz の部分の判定ができます。Buzz も同様に、5で割れるかを調べればいいわけですね。

コードはちょっと長めなので、エッセンスだけを示すとこんなふうになります。

def sumDigit([head | []]), do: head - 48
def sumDigit([head | tail]), do: head - 48 + sumDigit(tail)

def oneDigit([head | []]), do: head - 48
def oneDigit(list), do: oneDigit(Integer.to_charlist(sumDigit(list)))

まず sumDigit は、[’7’,’5’] から 12 を計算する関数です。48を引いているのは、’0’ の ASCIIコードが48だからですね。また関数定義そのものがパターンマッチになっていて、引数はリストなんですが、

def sum( [head | []] ) の行では、リストが先頭の1要素しかないときにマッチし、次の行では一般的なリストにマッチしています。head が先頭の要素、tail は残りのリストにマッチします。

oneDigit は、sumDigit を繰り返して [‘7’,’5’] から最終的に3を得る関数です。たぶんよく読めば分かります。あとは最終的に得られた数をもとに判断してやれば同様に FizzBuzz が解けそうですね。

あとは自由に Elixir を触ったり、講師たちと話をする時間になりました。参加者の学生の一人は競技プログラミングをやっているとのことで、Elixir を使った競技プラグミングもやってみようかなといったことを話していました。

そもそもなんで Elixir なのか?

今回、どうして Elixir という若い言語が対象なのか?については、主催の獅々見さんがとてもいいことを言っていたので紹介したいと思います。

「学生がトップレベルになる簡単な方法、それは先人がいない分野に挑むことです。20年以上の歴史がある世界で10年努力しても、まだまだあなたの上はいくらでもいます。しかし、生まれたばかりの技術を今から10年学んだらどうなるでしょう? 10年後にはあなたは名高いエンジニアになっているはずです。」

いい言葉ですよね。Elixir は2012年に生まれた言語。少なくとも日本ではまだこの人!という人はいないように思うので、今から頑張ればきっとコミュニティをリードする人になれるでしょう。

ぼくが学生時代に、先生に聞いたことがあります。ITではどんどん新しい技術が出てくるけど、どれが生き残るかもわからず、勉強しても結局ムダになるかもしれない。どうしたらいいでしょう?と。先生の答えはこうでした。

「それはね、無駄になることを恐れずにどんどん新しいことを学ぶしかないです。」

これは打ちのめされましたね。大変ですけど、間違いなく正論なんです。獅々見さんの言葉で、このエピソードを思い出しました。

なんで FizzBuzz なのか?

ところで講師の城門さんは、いろんな FizzBuzz の解き方を集める FizzBuzz コレクターなんだそうです。なので今回のお題も FizzBuzz だったんですね。

FizzBuzzの他の解き方では、golang で go routine を使って3秒ごとに Fizz、5秒ごとに Buzz、1秒ごとにnと出力するやり方もお気に入りです。出力するのに100秒かかります。

なんとなく想像つきますでしょうか。頭いいですけど、なかなか変態じみていますね。

まとめ

まず、Elixir については素直に面白そうだなと思いました。パターンマッチや無名関数の構文も素直できれいです。本文では省略しましたが、文字列の結合が <> なのはちょっと気持ち悪いなと思いましたが・・。「プログラミングElixir」という本が面白いそうなので、買って読んでみるつもりです。

今回は、勉強会そのものについての感動が大きかったです。学生どうしで教えあうことで全体としてレベルアップするっていうのが、主体的な学びの場っていう感じでいいなと。偉い人をつれてきてスライドを読んでもらうのも1つの方法ですが、それは受動的になりがちと思うんですよね。もちろんそれが主体的に学ぶきっかけになればいいわけですが。

今回行った勉強会:「【大学生・大学院生限定】最新技術キャッチアップ勉強会(Elixir編)」
http://techsalon.connpass.com/event/41486/

三土たつお。1976年生まれ。プログラマー、ライター。プログラマーとしてはふだんPHPを書いてます。ライターとしてはニフティのデイリーポータルZとかで書いてます。近著「街角図鑑」(実業之日本社)。
http://mitsuchi.net/

勉強会に行ってみた!第44回「最新技術キャッチアップ勉強会(Elixir編)」

この記事はどうでしたか?

おすすめの記事

キャリアを考える

BACK TO TOP ∧

FOLLOW