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:foldを使ってみた

  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

これは実際に私が行った中で最も近いですが、エラー エラーが発生します: This expression has type (string * value) list but an expression was expected of type (string * 'a list) list その理由がわかります。これは、list_help 関数の基本ケースで空のリストを返しているためです。構文エラーを修正したとしても、これは実際には上記の最初の 2 つのアプローチでは問題になります。これは、「なぜこれが機能しないのか」というより具体的な質問につながります。どうやって何も返さないの?() は機能しません。それを行う方法を理解するには、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
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 に答える