我目前正在攻读ocaml的期末考试并遇到问题,并且想知道是否有人会花时间帮忙。我正在做一个我们的教授发布here的练习决赛,特别是2号。问题是:
在这个问题中,我们将使用Ocaml数据结构来表示Python样式的命名空间。请考虑以下数据类型声明:
type name_space = EmptyNameSpace
| Info of (string * value) list * name_space
and value = Int of int
| Method of (name_space -> int -> int)
名称空间是空名称空间,或者包含一些信息。它包含的信息是字符串到值绑定的列表,以及指向父名称空间的指针。值可以是int,也可以是方法。方法将名称空间作为第一个参数(自指针)和一个附加整数,并返回一个整数。 假设我们有以下Python代码:
class SimpleObj1: a=0
def f(self, i): return i+1
class SimpleObj2 (SimpleObj1):
def g(self, i): return i+2
SimpleObj2()
通过调用SimpleObj2()创建的对象将在我们的OCaml数据结构中表示如下:
let method_f self i = i+1
let SimpleObj1 = Info([("a", Int(0)); ("f", Method(method_f))], EmptyNameSpace)
let method_g self i = i+2
let SimpleObj2 = Info([("g", Method(method_g))], SimpleObj1)
编写一个ocaml函数,它将查找名称空间中的值并返回它。例如,查找SimpleObj2“a”将返回Int(0)。
这就是问题所在。我已经尝试了一些东西,但是我受到语法错误的困扰,这些错误对我来说没有多大意义,或者我只是没有做正确的事情。我觉得我的逻辑是合理的,我几乎就在那里,但我可能很远,我不是很擅长ocaml。 尝试1:我尝试使用折叠
let rec lookup ns str =
let foldfn acc (str', val) =
if str' = str then val else acc
in
let base = [] in
match ns with
| EmptyNameSpace -> raise NotFound
| Info (l, parent) ->
match List.fold_left foldfn base l with
| value val -> val
| [] -> lookup parent str
由于某种原因,这给了我一个语法错误(在let letfn acc(str',val)中是不匹配的。我不知道是什么给了我这个,因为它显然是匹配的。会不会有其他原因导致ocaml抛出这个错误?
尝试2:没有折叠而只是递归。我可能也不擅长折叠。
let rec lookup ns str =
let rec list_help l =
match l with
| [] -> []
| (str',va)::t -> if str' = str then va else list_help t
in
match ns with
| EmptyNameSpace -> []
| Info (l, parent) ->
(match list_help l with
| [] -> lookup parent str
| value v -> v)
这通过强调v给我一个语法错误。我不明白它为什么会这样做,我有一个数据类型的值,我认为匹配它就好了。在ocaml数据类型中是否存在某些我不理解的细微差别。
尝试3:我试图通过编码来修复上面的奇怪语法错误(不好的做法,但我试图让它工作)。为了节省空间,我只会将更改发布到最后一场比赛,其他一切都是相同的。
match ns with
| EmptyNameSpace -> []
| Info (l, parent) ->
let ans = list_help l in
if ans = [] then lookup ns str
else ans
这实际上是我最接近的但却给出了错误 错误:此表达式具有类型(字符串*值)列表 但是表达式需要类型(字符串*'列表)列表 我明白为什么会这样。我是因为我在list_help函数的基本情况下返回一个空列表。即使我修复了语法错误,这实际上也是前两种方法中的问题。这引出了一个更具体的问题,然后“嘿,为什么这不起作用”。这是怎么回事? ()不起作用。我不太了解ocaml了解如何做到这一点。我感谢任何愿意花时间帮助我理解这一点的人。另外如果你想在同一个测试中对问题1c的折叠函数进行一次尝试,我也会非常感激,但是这个最让我烦恼的是,我可以找出一个足够的时间。
编辑:以防你需要异常NotFound定义,否则将抛出完全不同的错误。还有没有曾经的家庭作业标签?这不是功课,但非常接近它。
Edit2:想出来了。我做了很多工作。
let rec lookup ns str =
match ns with
| EmptyNameSpace -> raise NotFound
| Info ([], parent) -> lookup parent str
| Info ((k,v)::t, parent) -> if k = str then v else lookup (Info (t,parent)) str
答案 0 :(得分:4)
第一个示例中的错误是由于val
是关键字。但是,是的,还有一个错误,因为
| value v -> ...
| [] -> ...
不正确,我不确定你的意思。您应该修复一个基础类型错误。
您应该考虑使用List.assoc
函数返回与关联列表(对列表)中的键关联的值,或异常Not_found
。
PS:记录中,这是我想到的代码(未经测试)
let rec lookup ns key = match ns with
| EmptyNameSpace -> raise Not_found
| Info (scope, parent) ->
try List.assoc key scope
with Not_found -> lookup parent key