2

我目前正在准备 ocaml 的期末考试,遇到了一个问题,想知道是否有人愿意花时间提供帮助。我正在做我们的教授在这里发布的练习期末考试,特别是第 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

出于某种原因,这给了我一个语法错误,即 ( in let foldfn 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

这实际上是我最接近的,但给出了错误错误:此表达式具有类型 (string * value) 列表,但预期的表达式类型为 (string * 'a list) list 我可以看到为什么会这样。这是因为我在 list_help 函数的基本情况下返回了一个空列表。即使我修复了语法错误,这实际上也是上述前两种方法中的一个问题。这让我想到了一个更具体的问题,然后是“嘿,为什么这不起作用”。我怎么会什么都不返回?() 不起作用。我对 ocaml 的了解还不够,无法理解如何做到这一点。我感谢任何愿意花时间帮助我理解这一点的人。此外,如果您想在同一个测试中尝试问题 1c 的折叠功能,我也将不胜感激,但这个最困扰我,

编辑:以防万一您需要定义 NotFound 异常,否则将抛出一个完全不同的错误。以前不是有作业标签吗?这不是家庭作业,但非常接近。

编辑2:想通了。我做了很多工作。

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
4

1 回答 1

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
于 2013-06-10T06:00:49.107 回答