CS52 - Spring 2017 - Class 10
Example code in this lecture
digit_addition.sml
mutual_bad.sml
mutual.sml
mutual2.sml
Lecture notes
admin
- assignment 4
- collaboration
- CS lunch today
handling exceptions
- Quick recap:
- declaring exception
exception A;
- to raise an exception, you just put:
raise A
somewhere in the code
- If we call a function (or do an operation) that could raise an exception, we can try and catch/handle it
- In Java, this is done as:
try{
code_with_possible_exception
}catch(name_of_exception){
code_to_run_if_exception_happens
}
- In SML, it is similar, but the syntax is different
code_with_possible_exception handle
name_of_exception => code_to_run_if_exception_happens
- In SML both code_with_possible_exception and code_to_run_if_exception_happens need to be expressions that represent the same type
- If you want to handle multiple expressions (like having multiple catch statements in java), you can just list more of them using |
exceptions with more information
- the exceptions we've seen so far don't have any information except that an exception has occurred
- we can also declare exception to bring extra information along:
exception B of string;
exception C of int;
exception D of (int * int);
- These statements declare an expression that must have extra information when it is raise, e.g.
raise B "something bad happened";
raise C 0;
raise D (1,-1);
- In the handle expression, you can then access this information, e.g.
code_with_possible_exception handle
(B s) => ...
| (C n) => ...
| (D t) => ...
look at
digit_addition.sml code
- simple set of functions for doing digit-wise operations
- it's a little contrived, but it allows me to illustrate the points
- operation defines a new type for the 4 operations we will support
- BadOperation is the exception that we will raise
- checkDigit
- checks to make sure it's a valid digit
- if not raises an exception with information
- if it is, simply returns the value
- eval
- evaluates an operation on two inputs
- note that checkDigit might raise an exception
- or we might raise it if we find divide by 0
- eval2
- does the same thing
- shows an example of handling an exception without any extra information
- DivByZero is the exception that is raised by the system if you try and divide by 0
- calculate1
- calls eval and handles the exception using the option type
- calculate2
- calls eval and returns a string
- if it works, it has the answer
- if there is an exception, it prints the message
look at
mutual_bad.sml code
- What do these two functions do?
- determine if a number is even or odd
- How do they do it?
- a number is even if the number minus 1 is odd
- a number is odd if the number minus 1 is even
- What will happen if I try and "use" this file?
- SML is going to complain!
- in isEven, isOdd isn't defined yet.
- Can I just switch the order of the two function?
- No! Then isEven won't be defined
mutually recursive functions
- These functions are what are known as mutually recursive functions
- They are two functions that are recursive, but recurse by calling eachother, i.e. A calls B and B calls A.
- In SML, we have to tell the compiler that the functions we're declaring are mutually recursive.
- Look at
mutual.sml code
- to do this, instead of ending the first function with a semicolon we move on to the next line and begin the next function with "and" instead of "fun"
- you can do this for as many functions as you'd like
- SML will wait to examine all of the functions until a semicolon is reached.
Look at
mutual2.sml code
- What do these functions do?
- select every other element from a list
- everyOtherEven starts with the 2nd element
- everyOtherOdd starts with the 1st element