ErlangでFizzBuzz
-module(fizzbuzz). -export([exec/0]). % 1からNまでのリストを作る関数 seq(0) -> []; seq(N) -> seq(N-1) ++ [N]. % 数値を対応するFizzBuzz文字列に変換する関数 num_to_fizzbuzz(N) -> if N rem 15 == 0 -> "FizzBuzz"; N rem 5 == 0 -> "Buzz"; N rem 3 == 0 -> "Fizz"; true -> integer_to_list(N) end. % 数値のリストをFizzBuzz文字列のリストに変換する関数 nums_to_fizzbuzzs(Ns) -> lists:map(fun num_to_fizzbuzz/1, Ns). % 文字列のリストを連結する関数 join(_, []) -> ""; join(Delimiter, [X|XS]) -> X ++ Delimiter ++ join(Delimiter, XS). % 1からNまでのFizzBuzz文字列を作成する関数 fizzbuzz(N) -> join("~n", nums_to_fizzbuzzs(seq(N))). % FizzBuzz実行 exec() -> io:format(fizzbuzz(100)).
新しく覚えたこと
「%」より右はコメントになる。
% コメントだよ increment(N) -> N + 1 % 1をプラスする関数だよ
リストの連結は「++」
[1,2,3] ++ [4,5,6]. % [1,2,3,4,5,6]
文字列もリストなので「++」で連結する。
"Hello " ++ "World!". % "Hello World!"
関数の引数にパターンマッチできる。Haskellみたい。
以下は1からNまでのリストを作る関数
seq(0) -> []; % 引数が0だったら空のリストを返す。 seq(N) -> seq(N-1) ++ [N]. % 引数が0じゃなかったらseq(N-1)の末尾にNを加えたものを返す。
引数のパターンで分けた各関数たちは「;」でつながないといけないみたいだ。
if式もパターンマッチみたいに書く。
if N rem 15 == 0 -> "FizzBuzz"; N rem 5 == 0 -> "Buzz"; N rem 3 == 0 -> "Fizz"; true -> integer_to_list(N) end.
ifからendまでが1つの式で、条件を上から順番に評価していって最初にtrueになったところの式を評価して返す。
関数定義には1つの式しか書けない。
exec() -> Result = fizzbuzz(100). io:format(Result).
こんな風には書けない。
でも複数の式を連結して1つの式にする「,」という演算子があるので
exec() -> Result = fizzbuzz(100), io:format(Result).
っていう風に書けばいける。
無名関数は「fun」と「end.」を使って書く。
Fn = fun(N) -> N + 1 end.
名前のついた関数を値として使う時も「fun」を使う。名前だけじゃダメで引数の数まで指定してあげないといけない。
incr(N) -> N + 1. Fn = fun incr/1.
ループがない。変数の再代入ができないのだからループ構文というのはできないとのこと。
リストを作ってlists:mapやlists: foreachでエンヤコラするしかない。
lists:foreach(fun(N) -> io:format("~b~n", [N]) end, [1,2,3]).
lists:map(fun(N) -> N * 2 end, [1,2,3]). % [2,4,6]