之前的函数good_max在参数xs为空数组的时候返回0是非常糟糕的编程风格,我们有下面的一些方法可以考虑:
- 抛出一个异常(后续介绍)
- 返回一个空List或一个元素的List(也不是好的风格,因为此类情况在ML中很常见,并且ML为该情况已经设计了一种类型)
Options
- 语法(syntax):
t option
t是任意类型绑定,类型t list
- 构建(Building):
NONE:类型'a option(类似[ ]有类型'a list)
SOME e:类型t option如果表达式e有类型t(类似e :: [ ])
NONE
SOME 1 (* int option *)
SOME "a" (* string option *)
- 取值(Accessing):
isSome:类型'a option -> bool
valOf:类型'a option -> 'a(如果参数为NONE会抛出异常)
实例
fun better_max (xs : int list) =
if null xs
then NONE
else
let val tl_ans = better_max(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
then tl_ans
else SOME (hd xs)
end
(* val better_max = fn : int list -> int option *)
上面代码还有一点可以考虑优化,对better_max的递归调用,每一次都调用isSome tl_ans和valOf tl_ans去检查tl_ans是一个SOME还是一个NONE(如果xs很长,那么会有大量重复的调用)。
fun better_max2 (xs : int list) =
if null xs
then NONE
else
let
fun max_nonempty (xs : int list) = (* 此处xs不为空是合理的假设 *)
if null (tl xs)
then hd xs
else
let val tl_ans = max_nonempty(tl xs)
in if hd xs > tl_ans then hd xs else tl_ans
end
in
SOME (max_nonempty xs)
end