我在SML中编写了以下函数:
fun find_value [] item = ~1.0
| find_value ((x:string,y:real)::xt) item =
if item = x then y
else find_value xt item;
此函数获取列表string * real
和string
,并返回具有相同string
的元素的值。例如:
- find_value [("goo",4.0),("boo",5.0)] "goo";
val it = 4.0 : real`.
问题在于我的实现,如果它没有找到包含~1.0
字符串的元素,它将返回x
。所以,如果我有一个值为~1.0
的元素,它将返回它,我不知道列表是否为空,或者该元素是否在列表中,或者是否有一个元素具有相同的字符串,价值~1.0
。
示例:
find_value [("goo",~1.0),("boo",5.0)] "goo";
find_value [] "goo";
两者都将返回val it = ~1.0
。还有其他想法可供实施吗?
答案 0 :(得分:0)
这是一个很棒的问题。这就是'选项类型(documentation,Q&A)的用途。
您的find_value
可能看起来像:
fun find_value [] _ = NONE
| find_value ((key,value)::pairs) key1 =
if key = key1
then SOME value
else find_value pairs key1
现在你的两个例子将是:
- find_value [("goo",~1.0),("boo",5.0)] "goo";
val it = SOME ~1 : real option
- find_value [] "goo";
val it = NONE : 'a option
现在find_value
的来电者必须检查该值是否存在,例如用:
case find_value "foo" of
NONE => ... do some error handling ...
| SOME value => ... proceed ...
不太安全的替代方案是例外:
exception NotFound of string
fun find_value [] key1 = raise NotFound key1
| find_value ((key,value)::pairs) key1 =
if key = key1
then value
else find_value pairs key1
这里的优点似乎是您不必解压缩结果,具体取决于是否找到了结果,如果您不知道如何正确处理未找到的值,您可以简单地推迟从捕获异常到调用堆栈中的正确点。
但缺点是你必须记住捕获异常并且你不能确定调用其他代码的代码将是无异常的,因为任何引发异常的函数都会“污染”它的调用者。
通常,在您学习如何使用强类型编程语言时,在代码中包含异常是很好的,因为编译器可以在运行程序时更好地推理可能的场景。