What is it, naokirin?

テスト駆動開発の練習(14) -OCaml&OUnitで円/ドル計算-

OCamlを最近始めましたが、まだTDDでOUnitを使ってプログラミング・・・とまではたどり着いていません。

はっきり言ってしまうと、OUnitで使われている構文がよくわからない、おまじない的な要素が今のところとても多いです。ですが、使わないと始まらない、ということで現在参考にしている

プログラミング in OCaml ~関数型プログラミングの基礎からGUI構築まで~

プログラミング in OCaml ~関数型プログラミングの基礎からGUI構築まで~

の練習問題のドルから円、円からドルを計算する関数を作る際にOUnitを使ってみました。

ギリギリTDDになってたかな?

ちなみにソースはこれ。(リファクタリングの余地がある気がするコード・・・)

let rate = 114.32

let usdToYen x = 
  let y = (x *. rate) in 
  if (int_of_float (y *. 10.)) mod 10 < 5 
    then (int_of_float (floor y)) 
    else int_of_float((floor y) +. 1.)

let yenToUsd x = 
  let y = ((float_of_int x) /. rate) in
  if (int_of_float (1000. *. y)) mod 10 < 5
    then floor(y *. 100.) /. 100.
    else floor(y *. 100. +. 1.) /. 100. 

usdyen.ml

open Usdyen
open OUnit

let testUsdToYen1 () = assert_equal 457 (usdToYen 4.)
let testUsdToYen2 () = assert_equal 229 (usdToYen 2.)

let testYenToUsd1 () = assert_equal 0.87 (yenToUsd 100)
let testYenToUsd2 () = assert_equal 0.92 (yenToUsd 105)

let tests =
  "suite">:::[ "testUsdToYen1">::testUsdToYen1; 
    "testUsdToYen2">::testUsdToYen2; 
    "testYenToUsd1">::testYenToUsd1; 
    "testYenToUsd2">::testYenToUsd2 ]

let _ =
  run_test_tt_main tests

usdyentest.ml

usdToYenが引数にドル(float型)を受け取って、それが何円(int型)かを返す関数。
yenToUsdが引数に円(int型)を受け取って、それが何ドル(float型)かを返す関数。

為替レートとして設定した114.32円/ドルは本にあった値を使いましたが、今のご時世だと81円/ドルくらいでしょうか。思ったとおりでしたが、どうしてもfloat型の計算のときに"."を忘れます。とくに10倍したりするときは"*. 10."と書かずに"*. 10"と書いてしまったりしていました。
コンパイラに結構な回数、怒られました。

ちなみに今回コンパイルしたのですが、参考にしている本ではファイルに分けてコンパイルというのがまだまだ先で、みずぴー日記の記事を参考にコンパイルしました。(mzpさんには環境構築の際にもお世話になりました。とても助かりました。)テストコードに関してはOUnitユーザガイドを。

そういえば、今日Coqというものを調べてみました。Coqというのは定理証明支援器(数学定理の証明の支援をするもの?)だそうで、少なからずOCamlとも縁があるようです。Twitterでつぶやいたところ、3回もリツイートされてしまって驚きました。これはOCaml→Coqへの流れを感じる・・・

修正:テストコードのassert_equalに渡す引数を『"結果"、"期待値"』の順で書いていたのを『"期待値"、"結果"』に書き直しました。