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