OCamlでのFizzBuzzの作り方

OCamlFizzBuzzを作ろうとしているところをありのままのっけておきます。かなり時間かかってます。


さて、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