这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
变体(Variants)
Ocaml 中的变体(variants)类似于枚举类型,用来表示多种可能的值。例如
utop # type day = Sun | Mon | Tue | Wed | Thu | Fri | Sat;;
type day = Sun | Mon | Tue | Wed | Thu | Fri | Sat
utop # let d = Tue;;
val d : day = Tue
变体(variant)的每一个单独的值在Ocaml中被称为构造器(constructors)。比如上面的例子中,Sun、Mon就是构造器。
对于变体来说,构造非常的简单: 只用写出构造器的名字就可以;对于访问:我们使用模式匹配。例如:
utop # let int_of_day d =
match d with
| Sun -> 1
| Mon -> 2
| Tue -> 3
| Wed -> 4
| Thu -> 5
| Fri -> 6
| Sat -> 7;;
val int_of_day : day -> int = <fun>
没有任何类型的将构造函数名称映射到 int 的自动方法,就像您对带有枚举的语言所期望的那样。
作用域
假设我们有两个类型拥有相同的构造器名字,例如
utop # type t1 = C | D;;
type t1 = C | D
utop # type t2 = D | E;;
type t2 = D | E
utop # let x = D;;
val x : t2 = D
我们可以发现最后的x的类型为t2。
单元测试
我们这里列举一个单元测试的例子
比如,我们要测试如下代码,在sum.ml中
let rec sum = function
| [] -> 0
| x :: xs -> x + sum xs
这里我们使用OUnit2来进行单元测试,安装OUnit2时使用opam OUnit2,写在test.ml:
open OUnit2
open Sum
let tests = "test suite for sum" >::: [
"empty" >:: (fun _ -> assert_equal 0 (sum []));
"singleton" >:: (fun _ -> assert_equal 1 (sum [1]));
"two_elements" >:: (fun _ -> assert_equal 3 (sum [1; 2]));
]
let _ = run_test_tt_main tests
我们详细的看其中的代码,
[
"empty" >:: (fun _ -> assert_equal 0 (sum []));
"one" >:: (fun _ -> assert_equal 1 (sum [1]));
"onetwo" >:: (fun _ -> assert_equal 3 (sum [1; 2]));
]
每一行是单独的测试例子。在操作符>::的左边是测试例子的名字,右边是具体的函数。
运行前我们创建dune文件,
(executable
(name test)
(libraries ounit2))
然后我们编译,并得到结果
➜ Ocaml dune build test.exe
➜ Ocaml dune exec ./test.exe
...
Ran: 3 tests in: 0.11 seconds.
OK
现在我们假设我们修改了sum.ml并且增加一个bug在里面:
let rec sum = function
| [] -> 1
| x :: xs -> x + sum xs
我们同样的进行编译得到结果
➜ Ocaml dune exec ./test.exe
FFF
============================================================
Error: test suite for sum:1:singleton.
File "/Users/dcl/Documents/workspace/Ocaml/_build/oUnit-test suite for sum-dcl-2.local#02.log", line 2, characters 1-1:
Error: test suite for sum:1:singleton (in the log).
Raised at OUnitAssert.assert_failure in file "src/lib/ounit2/advanced/oUnitAssert.ml", line 45, characters 2-27
Called from OUnitRunner.run_one_test.(fun) in file "src/lib/ounit2/advanced/oUnitRunner.ml", line 83, characters 13-26
not equal
第一行的FFF暗示OUnit返回三个错误案例。