คำสั่งการจับคู่ที่ทับซ้อนกันใน OCaml

ฉันกำลังทำการบ้านอยู่ โดยพื้นฐานแล้ว มันเป็นเวอร์ชันพื้นฐานของคณิตศาสตร์เชิงสัญลักษณ์ ข้อมูลโค้ดต่อไปนี้ทำงานได้ดีอย่างสมบูรณ์

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 ... *)

ตัวอย่างเช่น หากฉันป้อน "eval (Plus (Int 3) (Int 5)) []" ก็จะคืนค่า 8 อย่างถูกต้อง อย่างไรก็ตาม เมื่อฉันพยายามเพิ่มนิพจน์ "let" ก็ทำให้เกิดข้อผิดพลาด นี่คือตัวอย่างฟังก์ชัน eval ที่แก้ไขแล้วของฉัน:

(* 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" *)

ฉันเชื่อว่าเหตุผลก็คือคอมไพเลอร์เห็นโค้ดเป็น:

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 ... *)

หากสัญชาตญาณของฉันถูกต้องว่าเป็นข้อผิดพลาด ฉันจะแก้ไขได้อย่างไร

หากมีสาเหตุอื่นสำหรับข้อผิดพลาดของฉัน มันคืออะไร?


person JBolton    schedule 17.02.2015    source แหล่งที่มา
comment
ดู [ที่นี่][1]; คำตอบแรกใน Google [1]: stackoverflow.com/questions/ 257605/   -  person Frédéric Dumont    schedule 17.02.2015
comment
คุณพูดถูก คุณต้องล้อมนิพจน์การจับคู่ภายในด้วยวงเล็บหรือจุดเริ่มต้น-จุดสิ้นสุด   -  person didierc    schedule 17.02.2015


คำตอบ (1)


คุณควรกำหนดขอบเขตการจับคู่ภายในของคุณด้วยวงเล็บ (หรือเทียบเท่าทางวากยสัมพันธ์ begin/end) หรือแยกโค้ดของคุณออกเป็นฟังก์ชันตัวช่วยที่แยกจากกัน ฉันชอบอย่างหลังอย่างแน่นอน

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