LoginSignup
3
1

More than 5 years have passed since last update.

Erlangでfizzbuzz 高階関数使ってみた。

Last updated at Posted at 2017-09-23

Erlang勉強継続中です。

前回は高階関数を使っていませんでした。
せっかくなので今回無理やり使ってみました。

前回のfizzbuzz:
https://qiita.com/shiro01/items/c19ff58ba1598c3adefd

ほとんど変わりませんが、今回書いたコードです。

-module(hof_fizzbuzz).
-export([run/2, run/3]).

%% out:fizzbuzz結果を都度出力、list:fizzbuzz結果のリスト作成
%% 1~Endまでの数値をfizzbuzzする
run(out, End) when is_integer(End) -> fb_out_for(End);
run(list, End) when is_integer(End) -> fb_list_for(End);
run(_, _) -> io:format("e.g. : run(out, ~p)~n", [10]).

%% Start~Endまでの数値をfizzbuzzする
run(out, Start, End) when is_integer(Start), is_integer(End) -> fb_out_for(Start, End);
run(list, Start, End) when is_integer(Start), is_integer(End) -> fb_list_for(Start, End);
run(_, _, _) -> io:format("e.g. : run(out, ~p, ~p)~n", [10, 20]).

%% 繰り返しfizzbuzz結果を出力する。
fb_out_for(0) ->  io:format("~p:~n",[0]);
fb_out_for(End) when 0 < End -> fb_out_for(1, End, fun fb_out/1).
fb_out_for(I, End) when I =< End -> fb_out_for(I, End, fun fb_out/1).
fb_out_for(End, End, F) -> F(End);
fb_out_for(I, End, F) -> F(I), fb_out_for(I+1, End, F).

%% 与えられた数値のfizzbuzz結果を出力する
fb_out(0) -> io:format("~p:~n",[0]);
fb_out(Num) -> fb_out(Num, Num rem 3, Num rem 5).
fb_out(Num, 0, 0)-> io:format("~p:~p~n",[Num, fizzbuzz]);
fb_out(Num, 0, _)-> io:format("~p:~p~n",[Num, fizz]);
fb_out(Num, _, 0)-> io:format("~p:~p~n",[Num, buzz]);
fb_out(Num, _, _)-> io:format("~p:~n",[Num]).

%% 繰り返しfizzbuzz結果のリストを作る
fb_list_for(0) -> [0];
fb_list_for(End) when 0 < End -> fb_list_for([], 1, End, fun fb_list/2).
fb_list_for(I, End) when I =< End -> fb_list_for([], I, End, fun fb_list/2).
fb_list_for(Reslut, End, End, F) -> lists:reverse(F(Reslut,End));
fb_list_for(Reslut, I, End, F) -> fb_list_for(F(Reslut, I), I+1, End, F).

%% 与えられた数値のfizzbuzz結果をリストに追加する
fb_list(Reslut, 0) -> [0|Reslut];
fb_list(Reslut, Num) -> fb_list(Reslut, Num, Num rem 3, Num rem 5).
fb_list(Reslut, _Num, 0, 0)-> [fizzbuzz|Reslut];
fb_list(Reslut, _Num, 0, _)-> [fizz|Reslut];
fb_list(Reslut, _Num, _, 0)-> [buzz|Reslut];
fb_list(Reslut, Num, _, _)-> [Num|Reslut].

実行結果

1> c(hof_fizzbuzz).
{ok,hof_fizzbuzz}
2>
2> hof_fizzbuzz:run(list, 10).
[1,2,fizz,4,buzz,fizz,7,8,fizz,buzz]
3>
3> hof_fizzbuzz:run(out, 10).
1:
2:
3:fizz
4:
5:buzz
6:fizz
7:
8:
9:fizz
10:buzz
ok
4>
4> hof_fizzbuzz:run(list, 10, 20).
[buzz,11,fizz,13,14,fizzbuzz,16,17,fizz,19,buzz]
5>
5> hof_fizzbuzz:run(out, 10, 20).
10:buzz
11:
12:fizz
13:
14:
15:fizzbuzz
16:
17:
18:fizz
19:
20:buzz
ok
6>

fb_list_for/4について
最初は以下のように実装してました。

fb_list_for(Reslut, MaxNum, MaxNum, F) ->
    Reslut_buf = F(Reslut,MaxNum),
    lists:reverse(Reslut_buf);
fb_list_for(Reslut, I, MaxNum, F) ->
    Reslut_buf = F(Reslut, I),
    fb_list_for(Reslut_buf, I+1, MaxNum, F).

大して変わらない気もしますが、どっちがいいんだろう。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1