OCamlでのFizzBuzzの作り方
OCamlでFizzBuzzを作ろうとしているところをありのままのっけておきます。かなり時間かかってます。
さて、OCamlは関数型言語なので、手続き型のようにループ用の変数を使ったりするのは筋が悪い。
Lispならがちょがちょと論理を組んでいくのが向いているようだけど、さてOCamlだとどうなるのか、と言うと・・・。
List.mapがあるじゃん
OCamlには便利な関数 List.map が存在するじゃないか。これを使えば、
- 1 .. 100 が入ったリスト
- ある数字がFizz・Buzzに当てはまるかどうかチェックする関数
の二つを準備すれば仕事が終わる!
・・・と思って調べてみる*1と、List.mapは末尾再帰じゃない!!末尾再帰なのはList.rev_mapで、この関数はList.mapと返すものが同じだそうだ。
えーと、List.mapいらなくないのかな?
FizzBuzz 関数本体
# fun x -> if x mod 15 = 0 then "FizzBuzz" else if x mod 5 = 0 then "Buzz" else if x mod 3 = 0 then "Fizz" else string_of_int x;;
普通に行けばこんな感じか。
1 .. 100 のリスト
Lispで言うところの
(defun make-list (max i) (cons i (cond ((eql max i) nil) (t (make-list max (+ i 1))))))
こんなものを作れば問題なく作成できそう。
でも、調べてみるとArrayには便利な組み込み関数があるそうなので、そちらを使うことにする。
その便利な組み込み関数というのは、Array.init 。
「int型の引数を取って'a型を返す関数」を引数にとって'a型のArrayを返す関数を定義できる素敵な高階関数。
# Array.init 100 (fun x -> x+1);;
便利ですね。
配列にもmapがあることを確認
リストから配列に変えたので、とりあえず確認してみると、どうやらこちらでもmapがある模様。
したらば、これらを組み合わせれば出来上がり。
# Array.map (fun x -> if x mod 15 = 0 then "FizzBuzz" else if x mod 5 = 0 then "Buzz" else if x mod 3 = 0 then "Fizz" else string_of_int x) (Array.init 100 (fun x -> x+1));;
こうですか><わかりません><
関数initを知ったのはこちら↓
http://shuns.sakura.ne.jp/?Programming%2FOCaml%2FJokeFizzBuzz