Pernyataan kecocokan yang tumpang tindih di OCaml

Saat ini saya sedang mengerjakan tugas pekerjaan rumah. Pada dasarnya ini adalah versi matematika simbolik yang sangat mendasar. Cuplikan kode berikut berfungsi dengan baik.

let rec eval exp (vars:(string * int) list) = match exp with
    | Int n -> n
    | Plus (a, b) -> (eval a vars) + (eval b vars)
    (* ... more match statements ... *)

Misalnya jika saya memasukkan "eval (Plus (Int 3) (Int 5)) []" ia mengembalikan 8 dengan benar. Namun ketika saya mencoba menambahkan ekspresi "biarkan" itu memberikan kesalahan. Berikut ini cuplikan fungsi eval saya yang dimodifikasi:

(* either returns Some value or None *)
let rec findVar key l = ...

let rec eval exp (vars:(string * int) list) = match exp with
    | Id id -> match (findVar id vars) with
        | Some value -> value
        | None -> raise (Failure ("Unknown variable " ^ id))
    | Int n -> n
    | Plus (a, b) -> (eval a vars) + (eval b vars)
    (* ... more match statements ... *)

(* raises "Error: The variant type option has no constructor Int" *)

Saya yakin alasannya adalah kompiler melihat kode sebagai:

let rec eval exp (vars:(string * int) list) = match exp with
    | Id id -> match (findVar id vars) with
        | Some value -> value
        | None -> raise (Failure ("Unknown variable " ^ id))
        | Int n -> n
        | Plus (a, b) -> (eval a vars) + (eval b vars)
        (* ... more match statements ... *)

Jika intuisi saya benar bahwa ini adalah kesalahannya, bagaimana cara memperbaikinya?

Jika ada penyebab lain dari kesalahan saya, apa penyebabnya?


person JBolton    schedule 17.02.2015    source sumber
comment
Lihat [di sini] [1]; jawaban pertama di Google. [1]: stackoverflow.com/questions/ 257605/   -  person Frédéric Dumont    schedule 17.02.2015
comment
Anda benar, Anda harus membungkus ekspresi pencocokan batin Anda dengan tanda kurung atau awal-akhir.   -  person didierc    schedule 17.02.2015


Jawaban (1)


Anda harus membatasi kecocokan batin Anda dengan orang tua (atau padanan sintaksisnya begin/end), atau memasukkan kode Anda ke dalam fungsi pembantu terpisah. Saya lebih suka yang terakhir.

let rec eval exp (vars : (string * int) list) = match exp with
    | Id id -> eval_var vars id
    | Int n -> n
    | Plus (a, b) -> (eval a vars) + (eval b vars)
    (* ... more match statements ... *)
 and eval_var vars id = match findVar id vars with
    | Some v -> ...
person ivg    schedule 17.02.2015