使用Ocaml数据结构表示Python样式的命名空间

时间:2013-06-10 03:47:42

标签: functional-programming ocaml

我目前正在攻读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

1 个答案:

答案 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