![Page 1: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/1.jpg)
CompSci 220Programming Methodology
15: Understanding FP Error Handling Part 1
![Page 2: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/2.jpg)
Objectives
• Understanding Exceptions• Understanding RT with Exceptions• Handling Errors without Exceptions• The Option data type
![Page 3: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/3.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
![Page 4: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/4.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous.
![Page 5: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/5.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:
![Page 6: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/6.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:• A file does not exist when an attempt is made to open it.
![Page 7: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/7.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:• A file does not exist when an attempt is made to open it.• The network does not exist when an attempt is made to communicate.
![Page 8: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/8.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:• A file does not exist when an attempt is made to open it.• The network does not exist when an attempt is made to communicate.• An attempt to reference an object that is null.
![Page 9: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/9.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:• A file does not exist when an attempt is made to open it.• The network does not exist when an attempt is made to communicate.• An attempt to reference an object that is null.• An attempt to execute an illegal instruction.
![Page 10: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/10.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:• A file does not exist when an attempt is made to open it.• The network does not exist when an attempt is made to communicate.• An attempt to reference an object that is null.• An attempt to execute an illegal instruction.• An invalid argument is provided to a function.
![Page 11: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/11.jpg)
What is an exceptional situation?
• What is an exceptional situation/condition in a program?
• A situation when something occurs in a program that was unexpected or erroneous. For example:• A file does not exist when an attempt is made to open it.• The network does not exist when an attempt is made to communicate.• An attempt to reference an object that is null.• An attempt to execute an illegal instruction.• An invalid argument is provided to a function.• The run-‐time stack is exhausted (stack overflow exception).
![Page 12: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/12.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.
![Page 13: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/13.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:
![Page 14: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/14.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:• Retrieving a value from a Map that might not exist.
![Page 15: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/15.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:• Retrieving a value from a Map that might not exist.• Reading a program with syntax errors.
![Page 16: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/16.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:• Retrieving a value from a Map that might not exist.• Reading a program with syntax errors.• Compiling a program with type errors.
![Page 17: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/17.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:• Retrieving a value from a Map that might not exist.• Reading a program with syntax errors.• Compiling a program with type errors.• Reading bytes from a network that were corrupted.
![Page 18: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/18.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:• Retrieving a value from a Map that might not exist.• Reading a program with syntax errors.• Compiling a program with type errors.• Reading bytes from a network that were corrupted.• Reading bytes from a file that was corrupted.
![Page 19: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/19.jpg)
What is a non exceptional situation?
• Any situation in a program that is expected or possible.For example:• Retrieving a value from a Map that might not exist.• Reading a program with syntax errors.• Compiling a program with type errors.• Reading bytes from a network that were corrupted.• Reading bytes from a file that was corrupted.
• Typically, a non exceptional situation is one in which regular control flow and possible conditions can be determined and reported.
![Page 20: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/20.jpg)
Traditional Error Handling
• How did earlier languages (e.g., C) handle exceptional situations?• Integer return values would indicate success/failure.
// returns a non-negative integer (if successful) (file descriptor)int open(char* filename);
// returns number of bytes read, 0 if at end of file, -1 if errorint read(FILE* f, char** buf);
![Page 21: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/21.jpg)
Traditional Error Handling
• How did earlier languages (e.g., C) handle exceptional situations?• Integer return values would indicate success/failure.
// returns a non-negative integer (if successful) (file descriptor)int open(char* filename);
// returns number of bytes read, 0 if at end of file, -1 if errorint read(FILE* f, char** buf);
• What if it is difficult to determine what that return value should be.
Consider what error value you would use to access a map of ints?
![Page 22: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/22.jpg)
Error Handling with Exceptions
• Because C and other languages typically do not support multiple return values the idea of throwing exceptions came to fruition.
• When an exceptional condition occurs, “throw” an exception that will be “caught” by a surrounding try/catch block.
• If the try/catch block is not in the current function scope, prematurely escape from the function (not return) to find a try/catch block. Continue to do this until one is found or crash the program with a stack trace.
![Page 23: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/23.jpg)
Why are exceptions a problem in FP?
a) They are not a problem.b) They can only check non exceptional situations.c) They break referential transparency.d) They are not supported in functional languages.e) All of these.
![Page 24: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/24.jpg)
Referential Transparency
• Why do exceptions break referential transparency?
def failingFn(i: Int): Int =val y: Int = throw new Exception(“fail!”)try {
val x = 42 + 5x + y
}catch { case e: Exception => 43 }
A catch block is just a pattern matching block like the ones we’ve seen.
case e: Exception is a pattern that matches any Exception.
![Page 25: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/25.jpg)
Referential Transparency
• Why do exceptions break referential transparency?
def failingFn(i: Int): Int =val y: Int = throw new Exception(“fail!”)try {
val x = 42 + 5x + y
}catch { case e: Exception => 43 }
scala> failingFn(12)java.lang.Exception: fail!at .failingFn(<console>:8)……
![Page 26: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/26.jpg)
Referential Transparency
• Why do exceptions break referential transparency?
def failingFn(i: Int): Int =val y: Int = throw new Exception(“fail!”)try {
val x = 42 + 5x + y
}catch { case e: Exception => 43 }
scala> failingFn(12)java.lang.Exception: fail!at .failingFn(<console>:8)……
We can prove that y is referentiallytransparent. Do you remember how?
![Page 27: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/27.jpg)
Referential Transparency
• Why do exceptions break referential transparency?
def failingFn(i: Int): Int =val y: Int = throw new Exception(“fail!”)try {
val x = 42 + 5x + y
}catch { case e: Exception => 43 }
scala> failingFn(12)java.lang.Exception: fail!at .failingFn(<console>:8)……
We can prove that y is referentiallytransparent. Do you remember how?
Right, by forward substituting y with the value it refers to – this substitution should preserve the meaning of the program.
![Page 28: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/28.jpg)
Referential Transparency
• Why do exceptions break referential transparency?
def failingFn(i: Int): Int =try {
val x = 42 + 5x + ((throw new Exception(“fail!”)): Int)
}catch { case e: Exception => 43 }
Here, we have forward substituted the value of y into the x + y expression.
What happens if we run this?
![Page 29: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/29.jpg)
Referential Transparency
• Why do exceptions break referential transparency?
def failingFn(i: Int): Int =try {
val x = 42 + 5x + ((throw new Exception(“fail!”)): Int)
}catch { case e: Exception => 43 }
Clearly, the meaning is not preserved so y is not RT and neither is failingFn.
scala> failingFn(12)res1: Int = 43
![Page 30: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/30.jpg)
Contextual Requirements
• The meaning of an RT expression does not depend on context.• It can be reasoned about locally
![Page 31: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/31.jpg)
Contextual Requirements
• The meaning of an RT expression does not depend on context.• It can be reasoned about locally
• The meaning of non-‐RT expressions is context-‐dependent.• It requires global reasoning
![Page 32: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/32.jpg)
Contextual Requirements
• The meaning of an RT expression does not depend on context.• It can be reasoned about locally
• The meaning of non-‐RT expressions is context-‐dependent.• It requires global reasoning
• For example, the meaning of 42 + 5 doesn’t depend on the larger expression it is embedded in – it will always be 47.
![Page 33: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/33.jpg)
Contextual Requirements
• The meaning of an RT expression does not depend on context.• It can be reasoned about locally
• The meaning of non-‐RT expressions is context-‐dependent.• It requires global reasoning
• For example, the meaning of 42 + 5 doesn’t depend on the larger expression it is embedded in – it will always be 47.• But, the meaning of throw new Exception(“fail!”) is context-‐dependent. It takes on a different meaning depending on which tryblock it is nested within.
![Page 34: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/34.jpg)
Exceptions: Problem 1
• Exceptions break RT and introduce context dependence.
This moves us away from simple reasoning of the substitution model and making it possible to write confusing exception-‐based code.
This is the source of the folklore advice that exceptions should be used only for error handling (unexpected situations), not for control flow.
![Page 35: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/35.jpg)
Exceptions: Problem 2
• Exceptions are not type-‐safe.
The type of failingFn, Int => Int, tells us nothing about the fact that exceptions may occur.
The compiler will certainly not force callers of failingFn to make decisions about how to handle those exceptions. If we forget, they will not be detected until runtime.
Java forces you to make a decision for “checked” exceptions. But, this results in substantial boilerplate code and does not work for higher-‐order functions. (i.e., how would you implement List.map?)
![Page 36: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/36.jpg)
Why are exceptions a problem in FP?
a) They are not a problem.b) They can only check non exceptional situations.c) They break referential transparency.d) They are not supported in functional languages.e) All of these.
![Page 37: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/37.jpg)
Solution: Old Idea / New Context
• We’d like an alternative to exceptions without these drawbacks.
• But, we do not want to lose out on the primary benefit of exceptions: they allow us to consolidate and centralize error-‐handling logic.
![Page 38: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/38.jpg)
Solution: Old Idea / New Context
• We’d like an alternative to exceptions without these drawbacks.
• But, we do not want to lose out on the primary benefit of exceptions: they allow us to consolidate and centralize error-‐handling logic.
• The functional approach goes back to the C approach:instead of throwing an exception, we return a value indicating that an exceptional condition has occurred.
• Unlike C – this approach will be type-‐safe.
![Page 39: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/39.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
![Page 40: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/40.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
throw new ArithmeticException(“mean of empty list!”)else xs.sum / xs.length
![Page 41: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/41.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
throw new ArithmeticException(“mean of empty list!”)else xs.sum / xs.length
The mean function is an example of a partial function: it’s not defined for some inputs (and not implied by the input types).
What is a possible alternative?
![Page 42: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/42.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
0.0/0.0else xs.sum / xs.length
We could return the result of 0.0/0.0 which would be Double.NaN.
![Page 43: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/43.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
0.0/0.0else xs.sum / xs.length
We could return the result of 0.0/0.0 which would be Double.NaN. But, …
![Page 44: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/44.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
0.0/0.0else xs.sum / xs.length
1) It allows errors to silently propagate (caller forgets to check)
![Page 45: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/45.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
0.0/0.0else xs.sum / xs.length
1) It allows errors to silently propagate (caller forgets to check)2) Boilerplate code to check for “real” results
![Page 46: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/46.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
0.0/0.0else xs.sum / xs.length
1) It allows errors to silently propagate (caller forgets to check)2) Boilerplate code to check for “real” results3) It’s not applicable to polymorphic code (what would the return value be?)
![Page 47: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/47.jpg)
Alternative to Exceptions
• Consider a function that computes the mean of a list, which is undefined if the list is empty:
def mean(xs: Seq[Double]): Double =if (xs.isEmpty)
0.0/0.0else xs.sum / xs.length
1) It allows errors to silently propagate (caller forgets to check)2) Boilerplate code to check for “real” results3) It’s not applicable to polymorphic code (what would the return value be?)4) Demands a special policy on how you use mean that has nothing to do with mean.
![Page 48: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/48.jpg)
Alternative to Exceptions
• We could also redefine mean to supply an argument that tells us what to do in case we don’t know how to handle the input:
def mean(xs: Seq[Double], onEmpty: Double): Double =if (xs.isEmpty) onEmptyelse xs.sum / xs.length
Now, mean is a total function – but it requires the caller to know how to handle the undefined case and limits them to returning a Double.
Still, how do we know if it was undefined or our default value?
![Page 49: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/49.jpg)
The Option Data Type
• The solution is to represent explicitly in the return type that a function may not always have an answer.
• The Option data type allows us to defer to the caller for the error-‐handling strategy.
sealed trait Option[+A]case class Some[+A](get: A) extends Option[A]case object None extends Option[Nothing]
![Page 50: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/50.jpg)
Mean with Option
def mean(xs: Seq[Double]): Option[Double] =if (xs.isEmpty) Noneelse Some(xs.sum / xs.length)
The return type now reflects the possibility that the result may not always be defined.
We still always return a result of the declared type (Option[Double]) from our function – so mean is now a total function.
![Page 51: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/51.jpg)
Usage Patterns for Option
• There are many places where Option is used.• It is quite useful to use in your own programs to replace exceptions.• It appears in the Scala Standard Library:
• Map lookup for a given key returns Option
• List defines headOption and lastOption, both returning option containg the first or last elements if non-‐empty.
![Page 52: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/52.jpg)
Functions on Option
trait Option[+A] {def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
}
The Option type has several useful functions that allow us to transparently operate on an Option value.
![Page 53: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/53.jpg)
Functions on Option
trait Option[+A] {def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
}
Apply f if the Option is not None – it transparently unwraps/wraps a Some(x) and returns either None or Some(f(x)).
![Page 54: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/54.jpg)
Functions on Option
trait Option[+A] {def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
}
Apply f, which may fail, to the Option if not None:Some(4).flatMap((v) => Some(v+1)) == Some(5)
![Page 55: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/55.jpg)
Functions on Option
trait Option[+A] {def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
}
Returns the value of the Option or the default if the Option is None.Some(5).getOrElse(6) == 5, None.getOrElse(6) == 6
![Page 56: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/56.jpg)
Functions on Option
trait Option[+A] {def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
}
Don’t evaluate ob unless needed.Some(5).orElse(Some(6)) == Some(5), None.orElse(Some(6)) == Some(6)
![Page 57: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/57.jpg)
Functions on Option
trait Option[+A] {def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
}
Convert Some to None if the value doesn’t satisfy f.Some(4).filter(_ > 5) == None, Some(4).filter(_ < 5) == Some(4)
![Page 58: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/58.jpg)
Option Usage Scenarios
case class Employee(name: String, dept: String)
def lookupByName(name: String): Option[Employee] = …
val joeDepartment: Option[String] =lookupByName(“Joe”).map(_.dept)
Here, we get Joe’s department if Joe is an employee or None if Joe is not an employee.
![Page 59: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/59.jpg)
Option Usage Scenarios
case class Employee(name: String, dept: String)
def lookupByName(name: String): Option[Employee] = …
val joeDepartment: String =lookupByName(“Joe”).map(_.dept)
How might we extend this to return the department as a String, or “Not an employee” if “Joe” is not an employee?Write this down on paper! def map[B](f: A => B): Option[B]
def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
![Page 60: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/60.jpg)
Option Usage Scenarios
case class Employee(name: String, dept: String)
def lookupByName(name: String): Option[Employee] = …
val joeDepartment: String =lookupByName(“Joe”).map(_.dept).getOrElse(“Not an employee”)
How might we extend this to return the department as a String, or “Not an employee” if “Joe” is not an employee?Write this down on paper! def map[B](f: A => B): Option[B]
def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
![Page 61: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/61.jpg)
Option Usage Scenarios
case class Employee(name: String, dept: String)
def lookupByName(name: String): Option[Employee] = …
val joeDepartment: String =lookupByName(“Joe”).???
Assuming Joe is an employee, how might we return the department name if Joe is not in the “Accounting” department and“Default Dept.” if he is in “Accounting”?Write this down on paper!
def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]
![Page 62: CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives • Understanding)Exceptions • Understanding)RT)with)Exceptions • Handling)Errors)without)Exceptions](https://reader035.vdocuments.net/reader035/viewer/2022070912/5fb431d80bc498456f6f6ef0/html5/thumbnails/62.jpg)
Option Usage Scenarios
case class Employee(name: String, dept: String)
def lookupByName(name: String): Option[Employee] = …
val joeDepartment: String =lookupByName(“Joe”).map(_.dept).filter(_ != “Accounting”).getOrElse(“Default Dept.”)
Assuming Joe is an employee, how might we return the department name if Joe is not in the “Accounting” department and“Default Dept.” if he is in “Accounting”?Write this down on paper!
def map[B](f: A => B): Option[B]def flatMap[B](f: A => Option[B]): Option[B]def getOrElse[B >: A](default: => B): Bdef orElse[B >: A](ob: => Option[B]): Option[B]def filter(f: A => Boolean): Option[A]