【发布时间】:2021-04-07 16:42:51
【问题描述】:
我正在阅读 Modern Compiler Implementation in ML 一书,同时学习 sml。
我被第一章中的一个练习(1.1.b)难住了。 我们被要求实现一个维护键/值对的二叉树, 键是字符串,值是参数化类型。 我的数据类型定义如下
type key = string
datatype 'a tree = LEAF | TREE of 'a tree * key * 'a * 'a tree
我们被要求实现一个类型为'a tree * key -> 'a 的lookup 函数。
我不知道如何实现这个函数,因为我不知道当树是LEAF 时要返回什么。 'a 没有默认值。书中的说明并没有说明找不到密钥的方法,但它坚持函数必须返回类型'a。
这只是书中的一个错误,还是在 sml 中有正确的方法来做到这一点?
在这种情况下,我试图引发异常,但编译器显然不会让我在不捕获异常的情况下引发异常。
如果我在 Scala 中实现此功能,我会将返回类型更改为 Option[A],如果找不到密钥则返回 None;或者在 Common Lisp 中,我会传递一个延续来调用找到的值,然后如果找不到键,则根本不调用延续。
这是我的代码,还没有工作。
(* page 12, exercise 1.1 b *)
type key = string
datatype 'a tree = LEAF | TREE of 'a tree * key * 'a * 'a tree
val empty = LEAF
fun insert(key,value,LEAF) = TREE(LEAF,key,value,LEAF)
| insert(key,value,TREE(l,k,v,r)) =
if key<k
then TREE(insert(key,value,l),k,v,r)
else if key>k
then TREE(l,k,v,insert(key,value,r))
else TREE(l,key,value,r)
fun lookup(LEAF,key) = (* !!!HELP!!! I don't know what to do in this case *)
| lookup(TREE(l,k,v,r),key) = if k=key
then v
else if key<k
then lookup(l,key)
else lookup(r,key)
val t1 = insert("a",1,empty)
val t2 = insert("c",2,t1)
val t3 = insert("b",3,t2)
;
lookup(t3,"a");
lookup(t3,"b");
lookup(t3,"c");
lookup(t3,"d");
顺便说一句,我不明白为什么 emacs sml-mode 坚持缩进对 lookup 的调用。
【问题讨论】:
-
这只是一个基本的练习练习;让它以不匹配的模式失败。
-
re:“让它以不匹配的模式失败”?我明白了,错误消息只是来自我的测试用例
lookup(t3,"d"),而不是来自编译器。好的,谢谢,我相信我明白了。 -
如果你真的想要返回类型
'a并且不引发异常,你可以永远循环:)。尽管正如您所建议的那样,我可能只会在实践中使用选项类型。我确实有一个想法是你的if链可能会更好地替换为String.compare (k, key)上的套管。