Haskellらしいfizzbuzz/OCamlらしいfizzbuzz
30分プログラム、その61。Haskellらしいfizzbuzz/OCamlらしいfizzbuzzを書いてみよう。
fizzbuzz :: [Int]->[String] fizzbuzz = map f where f n | n `mod` 15 == 0 = "fizzbuzz" | n `mod` 3 == 0 = "fizz" | n `mod` 5 == 0 = "buzz" | otherwise = show n fizzbuzzList :: [String] fizzbuzzList = fizzbuzz [1..] main = mapM_ putStrLn $ take 100 fizzbuzzList
Haskellらしいところ。
- ポイントフリー
- 型宣言をしている
- ガード節を使っている
- 無限リストを使っている
- mapM_を使っている
let rec range n m = if n == m then [n] else n::(range (n+1) m);; let fizzbuzz l = let f = function n when n mod 15 == 0 -> "fizzbuzz" | n when n mod 3 == 0 -> "fizz" | n when n mod 5 == 0 -> "buzz" | n -> string_of_int n in List.map f l;; let _ = List.iter (Printf.printf "%s\n") (fizzbuzz (range 1 100));;
OCamlらしいところ
- 再帰にはrecがいる
- whenによるガード節。使い型を忘れてたのでぐぐったら自分の日記がでてきた
- List.iterを使っている。副作用がない言語だったら、これ無意味でしょ?
- Printf.printfを使っている。これ、型安全なんだぜ
あと、時間測定もしてみた。
言語 | real | user | sys |
---|---|---|---|
Haskell(runghc,インタプリタ) | 0m1.493s | 0m1.185s | 0m0.136s |
Haskell(ghc,ネイティブコンパイラ) | 0m0.052s | 0m0.006s | 0m0.015s |
OCaml(ocaml,インタプリタ) | 0m0.071s | 0m0.037s | 0m0.014s |
OCaml(ocamlc,バイトコンパイラ) | 0m0.014s | 0m0.004s | 0m0.006s |
OCaml(ocamlopt,ネイティブコンパイラ) | 0m0.016s | 0m0.002s | 0m0.008s |
要するに、runghcは遅い。
これを両方つくって、5分程度あまった。