Haskellを勉強中で無性に、腐るほどあるFizzBuzz(関数)が書きたくなった。
fizzbuzz :: Integer -> [String]
fizzbuzz 0 = []
fizzbuzz n
| n `mod` 15 == 0 = fizzbuzz(n - 1) ++ ["fizzbuzz"]
| n `mod` 3 == 0 = fizzbuzz(n - 1) ++ ["fizz"]
| n `mod` 5 == 0 = fizzbuzz(n - 1) ++ ["buzz"]
fizzbuzz n = fizzbuzz(n - 1) ++ [show n]
間違っているかもしれない解説
fizzbuzz :: Integer -> [String]
はfizzbuzz関数の型宣言。これはInteger
型を引数にしてString
の配列を返すという意味。これは書かなくても推論してくれるらしいがすごいH本によると書いたほうがいいらしい。
fizzbuzz 0 = []
はfizzbuzz 0
が来たら、
fizzbuzz n
| n `mod` 15 == 0 = fizzbuzz(n - 1) ++ ["fizzbuzz"]
| n `mod` 3 == 0 = fizzbuzz(n - 1) ++ ["fizz"]
| n `mod` 5 == 0 = fizzbuzz(n - 1) ++ ["buzz"]
は15か3か5で割れるかのガードで
fizzbuzz n = fizzbuzz(n - 1) ++ [show n]
はこぼれたやつ。
この関数は再帰的に呼ばれるので、例えばfizzbuzz 3
とすると、
fizzbuzz 3
-> fizzbuzz(2) ++ ["fizz"]
-> fizzbuzz(1) ++ ["2", "fizz"]
-> fizzbuzz(0) ++ ["1", "2", "fizz"]
->["1", "2", "fizz"]
となる(はず)。
呼ばれる順に詳しく見ていく
fizzbuzz n
| n `mod` 15 == 0 = fizzbuzz(n - 1) ++ ["fizzbuzz"]
| n `mod` 3 == 0 = fizzbuzz(n - 1) ++ ["fizz"]
| n `mod` 5 == 0 = fizzbuzz(n - 1) ++ ["buzz"]
はガードと呼ばれるもので、nがなんの倍数か判定している。それがわかったらfizzbuzz(n -1)
と対応する文字列をくっつけて返す。"fizzbuzz" : fizzbuzz(n - 1)
としたくなるが(自分だけ?)、これだと結果が逆になってしまう。
fizzbuzz n = fizzbuzz(n - 1) ++ [show n]
は上のガードからこぼれたら来るもので、こちらはshow n
でInteger -> String
している。
fizzbuzz 0 = []
は最後なので空の配列を返して終了
fizzbuzz 100
*Main> fizzbuzz 100
["1","2","fizz","4","buzz","fizz","7","8","fizz","buzz","11","fizz","13","14","fizzbuzz","16","17","fizz","19","buzz","fizz","22","23","fizz","buzz","26","fizz","28","29","fizzbuzz","31","32","fizz","34","buzz","fizz","37","38","fizz","buzz","41","fizz","43","44","fizzbuzz","46","47","fizz","49","buzz","fizz","52","53","fizz","buzz","56","fizz","58","59","fizzbuzz","61","62","fizz","64","buzz","fizz","67","68","fizz","buzz","71","fizz","73","74","fizzbuzz","76","77","fizz","79","buzz","fizz","82","83","fizz","buzz","86","fizz","88","89","fizzbuzz","91","92","fizz","94","buzz","fizz","97","98","fizz","buzz"]