It is sometimes possible that an input does not lead to a sensible result, eg:
let rec assoc key lst = match lst with
|(k,v)::t -> if key=k then v else (assoc key t)
|[] -> (* ? *)
We’ve used 'a option
before: None | Some v
What if there’s more than one kind of “bad input”?
What if there’s more than kind of bad input?
let rec parser token_list = match token_list with
| (Const _)::t | (Var _)::t -> ...
| OP::NOT::t -> let (bx,t1) = parser t in
(match t1 with RP::t2 -> (bx,t2)
| _ -> (* missing close paren *))
| AND::tl
| OR::tl -> parse_two ...
| _ -> (* what *)
and parse_bool_exp tl =
let (bx, t) = parser t in match t with
| [] -> bx
| _ -> (* extra tokens after closed expression... *)
let rec parser token_list = match token_list with
| (Const _)::t | (Var _)::t -> ...
| OP::NOT::t -> let (bx,t1) = parser t in
(match t1 with RP::t2 -> (bx,t2)
| _ -> Err "missing close paren")
| OP::AND::tl
| OP::OR::tl -> parse_two ...
| _ -> Err "unexpected token"
and parse_bool_exp tl =
let (bx, t) = parser t in match t with
| [] -> Result bx
| _ -> Err "Extra tokens in input"
What do we do with recursive results?
let rec parser token_list = match token_list with
| (Const _)::t | (Var _)::t -> ...
| OP::NOT::t -> let (bx,t1) = parser t in
(match (bx,t1) with (Result b,RP::t2) -> (bx,t2)
| (Err s, _) -> (Err s,t1)
| _ -> Err "missing close paren")
| OP::AND::tl
| OP::OR::tl -> parse_two ...
| _ -> Err "unexpected token"
and parse_bool_exp tl =
let (bx, t) = parser t in match t with
| [] -> Result bx
| _ -> Err "Extra tokens in input"
Exceptions provide non-local handling of exceptional conditions.
To define a new exception Constructor we declare an exception:
Examples already defined in Ocaml:
To raise an exception, we use the raise
keyword
raise : exn -> 'a
must be called with a valid exn
constructor
The arguments to the constructor must match the type of the constructor
Exceptions are handled using the try/with expression:
Tries to evaluate <expr>
:
If no exception is raised, the result is the value of <expr>
:
try 2 with _ -> 0 ≡ 2
If an exception is raised the first matching pattern’s body is returned:
try raise Not_found with Not_found -> 3 | _ -> 4 ≡ 3
Type rules for try
/with
:
<expr>
and each <body>
must have matching types
<pattern>
must match an exn
constructor
Exceptions provide non-local handling of exceptional conditions
When handled correctly, exceptions separate functionality from error recovery.
let rec parser token_list = match token_list with
| (Const _)::t | (Var _)::t -> ...
| OP::NOT::t -> let (bx,t1) = parser t in
(match t1 with RP::t2 -> (bx,t2)
| _ -> raise Unclosed)
| OP::AND::tl
| OP::OR::tl -> parse_two ...
| h::tl -> raise (Unexpected h)
and parse_bool_exp tl =
let (bx, t) = parser t in match t with
| [] -> bx
| _ -> raise (Extra t)
More about exceptions in Hickey, ch. 9. Some tricky bits…
try f x with p1 -> ...
: f x
is not in tail position
type of raise
: exn -> 'a
Type of Not_found
and (Invalid_argument "blah")
: exn
cs2041.org