私は現在 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