CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives •...

62
CompSci 220 Programming Methodology 15: Understanding FP Error Handling Part 1

Transcript of CompSci220 - GitHub Pagesumass-cs-220.github.io/weeks/09/15-fp-error-handling.pdf · Objectives •...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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]