Addem
Addem

Reputation: 3929

OCaml: Using `try` and `with` for larger programs

Suppose you have a sequence of expressions that potentially raise an exception. If it does, you want some long process to take place. If it doesn't you want a different long process to take place. In imperative languages you can usually do something like

try:
    ...
except:
    ...

but I can't seem to reproduce this in OCaml, because it seems like you can only check a single expression at a time for an exception. I also don't see how you can use the value, if it exists, or do something else if it doesn't.

For a more concrete, if trivial example: I have a function list_max that returns the max of a list if it's non-empty and raises an exception if it is empty. Suppose I have a list and want to assert that its max is 4, but I'm wrong and it's really an empty list. I can't seem to get the syntax right from explanations that I've found. I've tried the following and many permutations on it:

try (list_max [])
with
| Failure s -> -1
| _ -> assert (list_max [] = 4);;

[Edit: rather than the contrived example above, perhaps one that makes more sense would be: Suppose I want to unit test this list_max function. I know I can do

assert ( (list_max [1;2;3] = 3 );;

But how would I test that list_max correctly throws an exception on an empty list?]

Upvotes: 1

Views: 504

Answers (1)

glennsl
glennsl

Reputation: 29126

You can do the assert in the try expression, as long as it raises an exception that you don't catch. Any other exception, such as Assert_failure in this case, will pass through.

try assert (list_max [] = 4) with
| Failure s -> -1

But assert returns unit so this will be a type error in any case.

An alternative is to use the exception case in pattern matching:

match list_max [] with
| exception (Failure _) -> -1
| _ -> assert (list_max [] = 4)

(This still has a type error)

Finally, you might want to use the option or result type instead of exceptions, since they're much safer. The compiler won't let you just forget about the error conditions then. If list_max had returned an option, this would be:

match list_max [] with
| None -> -1
| Some _ -> assert (list_max [] = 4)

(Still has the type error though)

Upvotes: 3

Related Questions