Search code examples
functional-programmingsml

Standard ML: Basic Conversion to Uppercase Character


I'm trying to write a function that converts a lower case character to uppercase (if uppercase, leave unchanged).

Here's what I've written:

fun toUpper(myChar) =
    exception invalidCharacter;
    if ord(myChar) >= ord(#"A") andalso ord(myChar) <= ord(#"Z") then myChar
    else
        if ord(myChar) >= ord(#"a") andalso ord(myChar) <= ord("z") then
            chr(ord(myChar) - (ord(#"a") - ord(#"A")));
        else raise invalidCharacter;

I'm getting this compilation error:

Ullman.sml:66.12 Error: syntax error: inserting  EQUALOP

uncaught exception Compile [Compile: "syntax error"]
  raised at: ../compiler/Parse/main/smlfile.sml:15.24-15.46
             ../compiler/TopLevel/interact/evalloop.sml:44.55
             ../compiler/TopLevel/interact/evalloop.sml:292.17-292.20

Am I not allowed to define exceptions within a function as I've done?

Thanks for the help, bclayman


Solution

  • No, you will need to define the exception in a let expression, such as:

    fun toUpper(myChar) =
      let exception invalidCharacter;
      in if ord(myChar) >= ord(#"A") andalso ord(myChar) <= ord(#"Z") then myChar
         else
          if ord(myChar) >= ord(#"a") andalso ord(myChar) <= ord(#"z") then
              chr(ord(myChar) - (ord(#"a") - ord(#"A")))
          else raise invalidCharacter
      end
    

    That said, it is probably better practice to define your exception outside of the let expression, so that it can be caught by the user. For example, if you wanted to do this for a string, one might do:

    fun toUppers(str) = String.implode (map toUpper (String.explode str)) 
    

    There is no way to recover from the invalidCharacter exception, unless you handle all exceptions (which is generally bad practice):

    fun toUppers(str) =  
      String.implode (map toUpper (String.explode str)) handle e => (*do something*)
    

    Instead we would like:

    fun toUppers(str) =  
      String.implode (map toUpper (String.explode str)) handle invalidCharacter => (*do something*)