Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Option, Either, Try

Option, Either, Try

Know your library mini-series. How to use Scala library classes: Option, Either and Try. Functional exception handling, i.e. what to do with corner cases when they arise.

Michal Bigos

June 25, 2013
Tweet

More Decks by Michal Bigos

Other Decks in Programming

Transcript

  1. OPTION, EITHER, TRY AND WHAT TO DO WITH CORNER CASES

    WHEN THEY ARISE KNOW YOUR LIBRARY MINI-SERIES By / Michal Bigos @teliatko
  2. KNOW YOUR LIBRARY - MINI SERIES 1. Hands-on with types

    from Scala library 2. DO's and DON'Ts 3. Intended for rookies, but Scala basic syntax assumed 4. Real world use cases
  3. WHY NULL ISN'T AN OPTION CONSIDER FOLLOWING CODE S t

    r i n g f o o = r e q u e s t . p a r a m s ( " f o o " ) i f ( f o o ! = n u l l ) { S t r i n g b a r = r e q u e s t . p a r a m s ( " b a r " ) i f ( b a r ! = n u l l ) { d o S o m e t h i n g ( f o o , b a r ) } e l s e { t h r o w n e w A p p l i c a t i o n E x c e p t i o n ( " B a r n o t f o u n d " ) } } e l s e { t h r o w n e w A p p l i c a t i o n E x c e p t i o n ( " F o o n o t f o u n d " ) }
  4. WHY NULL ISN'T AN OPTION WHAT'S WRONG WITH NULL /

    * 1 . N o b o d y k n o w s a b o u t n u l l , n o t e v e n c o m p i l e r * / S t r i n g f o o = r e q u e s t . p a r a m s ( " f o o " ) / * 2 . A n n o y i n g c h e c k i n g * / i f ( f o o ! = n u l l ) { S t r i n g b a r = r e q u e s t . p a r a m s ( " b a r " ) / / i f ( b a r ! = n u l l ) { / * 3 . D a n g e r o f i n f a m o u s N u l l P o i n t e r E x c e p t i o n , e v e r b o d y c a n f o r g e t s o m e c h e c k * / d o S o m e t h i n g ( f o o , b a r ) / / } e l s e { / * 4 . O p t i o n a t e d d e t a i l e d f a i l u r e s , s o m e t i m e s f a i l u r e i n t h e e n d i s e n o u g h * / / / t h r o w n e w A p p l i c a t i o n E x c e p t i o n ( " B a r n o t f o u n d " ) / / } } e l s e { / * 5 . D e s i g n f l a w , j u s t o r i g i n a l e x c e p t i o n r e p l a c e m e n t * / t h r o w n e w A p p l i c a t i o n E x c e p t i o n ( " F o o n o t f o u n d " ) }
  5. DEALING WITH NON-EXISTENCE DIFFERENT APPROACHES COMPARED Java relies on sad

    n u l l Groovy provides null-safe operator for accessing properties Clojure uses n i l which is okay very often, but sometimes it leads to an exception higher in call hierarchy f o o ? . b a r ? . b a z
  6. GETTING RID OF NULL NON-EXISTENCE SCALA WAY Container with one

    or none element s e a l e d a b s t r a c t c l a s s O p t i o n [ A ] c a s e c l a s s S o m e [ + A ] ( x : A ) e x t e n d s O p t i o n [ A ] c a s e o b j e c t N o n e e x t e n d s O p t i o n [ N o t h i n g ]
  7. OPTION 1. States that value may or may not be

    present on type level 2. You are forced by the compiler to deal with it 3. No way to accidentally rely on presence of a value 4. Clearly documents an intention
  8. OPTION CREATING AN OPTION Never do this Rather use factory

    method on companion object v a l c e r t a i n = S o m e ( " S u n c o m e s u p " ) v a l p i t t y = N o n e v a l n o n S e n s e = S o m e ( n u l l ) v a l m u c h B e t t e r = O p t i o n ( n u l l ) / / R e s u l t s t o N o n e v a l c e r t a i n A g a i n = O p t i o n ( " S u n c o m e s u p " ) / / S o m e ( S u n c o m e s u p )
  9. OPTION WORKING WITH OPTION AN OLD WAY Don't do this

    (only in exceptional cases) / / A s s u m e t h a t d e f p a r a m [ S t r i n g ] ( n a m e : S t r i n g ) : O p t i o n [ S t r i n g ] . . . v a l f o o P a r a m = r e q u e s t . p a r a m ( " f o o " ) v a l f o o = i f ( f o o P a r a m . i s D e f i n e d ) { f o o P a r a m . g e t / / t h r o w s N o S u c h E l e m e n t E x c e p t i o n w h e n N o n e } e l s e { " D e f a u l t f o o " / / D e f a u l t v a l u e }
  10. OPTION PATTERN MATCHING Don't do this (there's a better way)

    v a l f o o = r e q u e s t . p a r a m ( " f o o " ) m a t c h { c a s e S o m e ( v a l u e ) = > v a l u e c a s e N o n e = > " D e f a u l t f o o " / / D e f a u l t v a l u e }
  11. OPTION PROVIDING A DEFAULT VALUE Default value is by-name parameter.

    It's evaluated lazily. / / a n y l o n g c o m p u t a t i o n f o r d e f a u l t v a l u e v a l f o o = r e q u e s t . p a r a m ( " f o o " ) g e t O r E l s e ( " D e f a u l t f o o " )
  12. OPTION TREATING IT FUNCTIONAL WAY Think of Option as collection

    It is biased towards S o m e You can m a p , f l a t M a p or compose Option(s) when it contains value, i.e. it's S o m e
  13. OPTION EXAMPLE Suppose following model and DAO c a s

    e c l a s s U s e r ( i d : I n t , n a m e : S t r i n g , a g e : O p t i o n [ I n t ] ) / / I n d o m a i n m o d e l , a n y o p t i o n a l v a l u e h a s t o b e e x p r e s s e d w i t h O p t i o n o b j e c t U s e r D a o { d e f f i n d B y I d ( i d : I n t ) : O p t i o n [ U s e r ] = . . . / / I d c a n a l w a y s b e i n c o r r e c t , e . g . i t ' s p o s s i b l e t h a t u s e r d o e s n o t e x i s t a l r e a d y }
  14. OPTION SIDE-EFFECTING Use case: Printing the user name / /

    S u p p o s e w e h a v e a n u s e r I d f r o m s o m e w h e r e v a l u s e r O p t = U s e r D a o . f i n d B y I d ( u s e r I d ) / / J u s t p r i n t u s e r n a m e u s e r O p t . f o r e a c h { u s e r = > p r i n t l n ( u s e r . n a m e ) / / N o t h i n g w i l l b e p r i n t e d w h e n N o n e } / / R e s u l t i s U n i t ( l i k e v o i d i n J a v a ) / / O r m o r e c o n c i s e u s e r O p t . f o r e a c h ( u s e r = > p r i n t l n ( u s e r ) ) / / O r e v e n m o r e u s e r O p t . f o r e a c h ( p r i n t l n ( _ ) ) u s e r O p t . f o r e a c h ( p r i n t l n )
  15. OPTION MAP, FLATMAP & CO. Use case: Extracting age /

    / E x t r a c t i n g a g e v a l a g e O p t = U s e r D a o . f i n d B y I d ( u s e r I d ) . m a p ( _ . a g e ) / / R e t u r n s O p t i o n [ O p t i o n [ I n t ] ] v a l a g e O p t = U s e r D a o . f i n d B y I d ( u s e r I d ) . m a p ( _ . a g e . m a p ( a g e = > a g e ) ) / / R e t u r n s O p t i o n [ O p t i o n [ I n t ] ] t o o / / E x t r a c t i n g a g e , t a k e 2 v a l a g e O p t = U s e r D a o . f i n d B y I d ( u s e r I d ) . f l a t M a p ( _ . a g e . m a p ( a g e = > a g e ) ) / / R e t u r n s O p t i o n [ I n t ]
  16. OPTION FOR COMPREHENSIONS Same use case as before Usage in

    left side of generator / / E x t r a c t i n g a g e , t a k e 3 v a l a g e O p t = f o r { u s e r < - U s e r D a o . f i n d B y I d ( u s e r I d ) a g e < - u s e r . a g e } y i e l d a g e / / R e t u r n s O p t i o n [ I n t ] / / E x t r a c t i n g a g e , t a k e 3 v a l a g e O p t = f o r { U s e r ( _ , S o m e ( a g e ) ) < - U s e r D a o . f i n d B y I d ( u s e r I d ) } y i e l d a g e / / R e t u r n s O p t i o n [ I n t ]
  17. OPTION COMPOSING TO LIST Use case: Pretty-print of user Different

    notation Both prints Rule of thumb: wrap all mandatory fields with Option and then concatenate with optional ones d e f p r e t t y P r i n t ( u s e r : U s e r ) = L i s t ( O p t i o n ( u s e r . n a m e ) , u s e r . a g e ) . m k S t r i n g ( " , " ) d e f p r e t t y P r i n t ( u s e r : U s e r ) = ( O p t i o n ( u s e r . n a m e ) + + u s e r . a g e ) . m k S t r i n g ( " , " ) v a l f o o = U s e r ( " F o o " , S o m e ( 1 0 ) ) v a l b a r = U s e r ( " B a r " , N o n e ) p r e t t y P r i n t ( f o o ) / / P r i n t s " F o o , 1 0 " p r e t t y P r i n t ( b a r ) / / P r i n t s " B a r "
  18. OPTION CHAINING Use case: Fetching or creating the user More

    appropriate, when U s e r is desired directly o b j e c t U s e r D a o { / / N e w m e t h o d d e f c r e a t e U s e r : U s e r } v a l u s e r O p t = U s e r D a o . f i n d B y I d ( u s e r I d ) o r E l s e S o m e ( U s e r D a o . c r e a t e ) v a l u s e r = U s e r D a o . f i n d B y I d ( u s e r I d ) g e t O r E l s e U s e r D a o . c r e a t e
  19. OPTION MORE TO EXPLORE s e a l e d

    a b s t r a c t c l a s s O p t i o n [ A ] { d e f f o l d [ B ] ( i f E m p t y : Ó B ) ( f : ( A ) Ó B ) : B d e f f i l t e r ( p : ( A ) Ó B o o l e a n ) : O p t i o n [ A ] d e f e x i s t s ( p : ( A ) Ó B o o l e a n ) : B o o l e a n . . . }
  20. IS OPTION APPROPRIATE? Consider following piece of code When something

    went wrong, cause is lost forever c a s e c l a s s U s e r F i l t e r ( n a m e : S t r i n g , a g e : I n t ) d e f p a r s e F i l t e r ( i n p u t : S t r i n g ) : O p t i o n [ U s e r F i l t e r ] = { f o r { n a m e < - p a r s e N a m e ( i n p u t ) a g e < - p a r s e A g e ( i n p u t ) } y i e l d U s e r F i l t e r ( n a m e , a g e ) } / / S u p p o s e t h a t p a r s e N a m e a n d p a r s e A g e t h r o w s F i l t e r E x c e p t i o n d e f p a r s e F i l t e r ( i n p u t : S t r i n g ) : O p t i o n [ U s e r F i l t e r ] t h r o w s F i l t e r E x c e p t i o n { . . . } / / c a l l e r s i d e v a l f i l t e r = t r y { p a r s e F i l t e r ( i n p u t ) } c a t c h { c a s e e : F i l t e r E x c e p t i o n = > w h a t T o D o I n T h e M i d d l e O f T h e C o d e ( e ) }
  21. INTRODUCING EITHER Container with disjoint types. s e a l

    e d a b s t r a c t c l a s s E i t h e r [ + L , + R ] c a s e c l a s s L e f t [ + L , + R ] ( a : L ) e x t e n d s E i t h e r [ L , R ] c a s e c l a s s R i g h t [ + L , + R ] ( b : R ) e x t e n d s E i t h e r [ L , R ]
  22. EITHER 1. States that value is either L e f

    t [ L ] or R i g h t [ R ] , but never both. 2. No explicit sematics, but by convention L e f t [ L ] represents corner case and R i g h t [ R ] desired one. 3. Functional way of dealing with alternatives, consider: 4. Again, it clearly documents an intention d e f d o S o m e t h i n g ( ) : I n t t h r o w s S o m e E x c e p t i o n / / w h a t i s t h i s s a y i n g ? t w o p o s s i b l e o u t c o m e s d e f d o S o m e t h i n g ( ) : E i t h e r [ S o m e E x c e p t i o n , I n t ] / / m o r e f u n c t i o n a l o n l y o n e r e t u r n v a l u e
  23. EITHER CREATING EITHER There is no E i t h

    e r ( . . . ) factory method on companion object. d e f p a r s e A g e ( i n p u t : S t r i n g ) : E i t h e r [ S t r i n g , I n t ] = { t r y { R i g h t ( i n p u t . t o I n t ) } c a t c h { c a s e n f e : N u m b e r F o r m a t E x c e p t i o n = > L e f t ( " U n a b l e t o p a r s e a g e " ) } }
  24. EITHER WORKING AN OLD WAY AGAIN Don't do this (only

    in exceptional cases) d e f p a r s e F i l t e r ( i n p u t : S t r i n g ) : E i t h e r [ S t r i n g , E x t e n d e d F i l t e r ] = { v a l n a m e = p a r s e N a m e ( i n p u t ) i f ( n a m e . i s R i g h t ) { v a l a g e = p a r s e A g e ( i n p u t ) i f ( a g e . i s R i g h t ) { R i g h t ( U s e r F i l t e r ( t i m e , r a t i n g ) ) } e l s e a g e } e l s e n a m e }
  25. EITHER PATTERN MATCHING Don't do this (there's a better way)

    d e f p a r s e F i l t e r ( i n p u t : S t r i n g ) : E i t h e r [ S t r i n g , E x t e n d e d F i l t e r ] = { p a r s e N a m e ( i n p u t ) m a t c h { c a s e R i g h t ( n a m e ) = > p a r s e A g e ( i n p u t ) m a t c h { c a s e R i g h t ( a g e ) = > U s e r F i l t e r ( n a m e , a g e ) c a s e e r r o r : L e f t [ _ ] = > e r r o r } c a s e e r r o r : L e f t [ _ ] = > e r r o r } }
  26. EITHER PROJECTIONS You cannot directly use instance of E i

    t h e r as collection. It's unbiased, you have to define what is your prefered side. Working on success, only 1st error is returned. e i t h e r . r i g h t returns R i g h t P r o j e c t i o n d e f p a r s e F i l t e r ( i n p u t : S t r i n g ) : E i t h e r [ S t r i n g , U s e r F i l t e r ] = { f o r { n a m e < - p a r s e N a m e ( i n p u t ) . r i g h t a g e < - p a r s e A g e ( i n p u t ) . r i g h t } y i e l d R i g h t ( U s e r F i l t e r ( n a m e , a g e ) ) }
  27. EITHER PROJECTIONS, TAKE 2 Working on both sides, all errors

    are collected. e i t h e r . l e f t returns L e f t P r o j e c t i o n d e f p a r s e F i l t e r ( i n p u t : S t r i n g ) : E i t h e r [ L i s t [ S t r i n g ] , U s e r F i l t e r ] = { v a l n a m e = p a r s e N a m e ( i n p u t ) v a l a g e = p a r s e A g e ( i n p u t ) v a l e r r o r s = n a m e . l e f t . t o O p t i o n + + a g e . l e f t . t o O p t i o n i f ( e r r o r s . i s E m p t y ) { R i g h t ( U s e r F i l t e r ( n a m e . r i g h t . g e t , a g e . r i g h t . g e t ) ) } e l s e { L e f t ( e r r o r s ) } }
  28. EITHER PROJECTIONS, TAKE 3 Both projection are biased wrappers for

    E i t h e r You can use m a p , f l a t M a p on them too, but beware This is inconsistent in regdard to other collections. v a l r i g h t T h i n g = R i g h t ( U s e r ( " F o o " , S o m e ( 1 0 ) ) ) v a l p r o j e c t i o n = r i g h t T h i n g . r i g h t / / T y p e i s R i g h t P r o j e c t i o n [ U s e r ] v a l r i g h t T h i n g A g a i n = p r o j e c t i o n . m a p ( _ . n a m e ) / / I s n ' t R i g h t P r o j e c t i o n [ U s e r ] b u t R i g h t [ U s e r ]
  29. EITHER PROJECTIONS, TAKE 4 It can lead to problems with

    for comprehensions. This won't compile. After removing syntactic suggar, we get We need projection again f o r { n a m e < - p a r s e N a m e ( i n p u t ) . r i g h t b i g N a m e < - n a m e . c a p i t a l i z e } y i e l d b i g N a m e p a r s e N a m e ( i n p u t ) . r i g h t . m a p { n a m e = > v a l b i g N a m e = n a m e . c a p i t a l i z e ( b i g N a m e ) } . m a p { c a s e ( x ) = > x } / / M a p i s n o t m e m b e r o f E i t h e r
  30. f o r { n a m e < -

    p a r s e N a m e ( i n p u t ) . r i g h t b i g N a m e < - R i g h t ( n a m e . c a p i t a l i z e ) . r i g h t } y i e l d b i g N a m e
  31. EITHER FOLDING Allows transforming the E i t h e

    r regardless if it's R i g h t or L e f t on the same type Accepts functions, both are evaluated lazily. Result from both functions has same type. / / O n c e u p o n a t i m e i n c o n t r o l l e r p a r s e F i l t e r ( i n p u t ) . f o l d ( / / B a d ( L e f t ) s i d e t r a n s f o r m a t i o n t o H t t p R e s p o n s e e r r o r s = > B a d R e q u e s t ( " E r r o r i n f i l t e r " ) / / G o o d ( R i g h t ) s i d e t r a n s f o r m a t i o n t o H t t p R e s p o n s e f i l t e r = > O k ( d o S o m e t h i n g W i t h ( f i l t e r ) ) )
  32. EITHER MORE TO EXPLORE s e a l e d

    a b s t r a c t c l a s s E i t h e r [ + A , + B ] { d e f j o i n L e f t [ A 1 > : A , B 1 > : B , C ] ( i m p l i c i t e v : < : < [ A 1 , E i t h e r [ C , B 1 ] ] ) : E i t h e r [ C , B 1 ] d e f j o i n R i g h t [ A 1 > : A , B 1 > : B , C ] ( i m p l i c i t e v : < : < [ B 1 , E i t h e r [ A 1 , C ] ] ) : E i t h e r [ A 1 , C ] d e f s w a p : P r o d u c t w i t h S e r i a l i z a b l e w i t h E i t h e r [ B , A ] }
  33. THROWING AND CATCHING EXCEPTIONS SOMETIMES THINGS REALLY GO WRONG You

    can use classic t r y / c a t c h / f i n a l l y construct d e f p a r s e A g e ( i n p u t : S t r i n g ) : E i t h e r [ S t r i n g , I n t ] = { t r y { R i g h t ( i n p u t . t o I n t ) } c a t c h { c a s e n f e : N u m b e r F o r m a t E x c e p t i o n = > L e f t ( " U n a b l e t o p a r s e a g e " ) } }
  34. THROWING AND CATCHING EXCEPTIONS SOMETIMES THINGS REALLY GO WRONG, TAKE

    2 But, it's t r y / c a t c h / f i n a l l y on steroids thanks to pattern matching t r y { s o m e H o r r i b l e C o d e H e r e ( ) } c a t c h { / / C a t c h i n g m u l t i p l e t y p e s c a s e e @ ( _ : I O E x c e p t i o n | _ : N a s t y E x p c e p t i o n ) = > c l e a n U p M e s s ( ) / / C a t c h i n g e x c e p t i o n s b y m e s s a g e c a s e e : A n o t h e r N a s t y E x c e p t i o n i f e . g e t M e s s a g e c o n t a i n s " W r o n g a g a i n " = > c l e a n U p M e s s ( ) / / C a t c h i n g a l l e x c e p t i o n s c a s e e : E x c e p t i o n = > c l e a n U p M e s s ( ) }
  35. THROWING AND CATCHING EXCEPTIONS SOMETIMES THINGS REALLY GO WRONG, TAKE

    3 It's powerful, but beware Never do this! Prefered approach of catching all t r y { s o m e H o r r i b l e C o d e H e r e ( ) } c a t c h { / / T h i s w i l l m a t c h s c a l a . u t i l . c o n t r o l . C o n t r o l T h r o w a b l e t o o c a s e _ = > c l e a n U p M e s s ( ) } t r y { s o m e H o r r i b l e C o d e H e r e ( ) } c a t c h { / / T h i s w i l l m a t c h s c a l a . u t i l . c o n t r o l . C o n t r o l T h r o w a b l e t o o c a s e t : C o n t r o l T h r o w a b l e = > t h r o w t c a s e _ = > c l e a n U p M e s s ( ) }
  36. WHAT'S WRONG WITH EXCEPTIONS 1. Referential transparency - is there

    a value the RHS can be replaced with? No. 2. Code base can become ugly 3. Exceptions do not go well with concurrency v a l s o m e t h i n g = t h r o w n e w I l l e g a l A r g u m e n t E x c e p t i o n ( " F o o i s m i s s i n g " ) / / R e s u l t t y p e i s N o t h i n g
  37. EXCEPTION HANDLING FUNCTIONAL WAY Please welcome i m p o

    r t s c a l a . u t i l . c o n t r o l . _ and Collection of T h r o w a b l e or value s e a l e d t r a i t T r y [ A ] c a s e c l a s s F a i l u r e [ A ] ( e : T h r o w a b l e ) e x t e n d s T r y [ A ] c a s e c l a s s S u c c e s s [ A ] ( v a l u e : A ) e x t e n d s T r y [ A ]
  38. TRY 1. States that computation may be S u c

    c e s s [ T ] or may be F a i l u r e [ T ] ending with T h r o w a b l e on type level 2. Similar to O p t i o n , it's S u c c e s s biased 3. It's t r y / c a t c h without boilerplate 4. Again it clearly documents what is happening
  39. TRY LIKE OPTION All the operations from O p t

    i o n are present s e a l e d a b s t r a c t c l a s s T r y [ + T ] { / / T h r o w s e x c e p t i o n o f F a i l u r e o r r e t u r n v a l u e o f S u c c e s s d e f g e t : T / / O l d w a y c h e c k s d e f i s F a i l u r e : B o o l e a n d e f i s S u c c e s s : B o o l e a n / / m a p , f l a t M a p & C o . d e f m a p [ U ] ( f : ( T ) Ó U ) : T r y [ U ] d e f f l a t M a p [ U ] ( f : ( T ) Ó T r y [ U ] ) : T r y [ U ] / / S i d e e f f e c t i n g d e f f o r e a c h [ U ] ( f : ( T ) Ó U ) : U n i t / / D e f a u l t v a l u e d e f g e t O r E l s e [ U > : T ] ( d e f a u l t : Ó U ) : U / / C h a i n i n g d e f o r E l s e [ U > : T ] ( d e f a u l t : Ó T r y [ U ] ) : T r y [ U ] }
  40. TRY BUT THERE IS MORE Assume that Recovering from a

    Failure Converting to O p t i o n d e f p a r s e A g e ( i n p u t : S t r i n g ) : T r y [ I n t ] = T r y ( i n p u t . t o I n t ) v a l a g e = p a r s e A g e ( " n o t a n u m b e r " ) r e c o v e r { c a s e e : N u m b e r F o r m a t E x c e p t i o n = > 0 / / D e f a u l t v a l u e c a s e _ = > - 1 / / A n o t h e r d e f a u l t v a l u e } / / R e s u l t i s a l w a y s S u c c e s s v a l a g e O p t = a g e . t o O p t i o n / / W i l l b e S o m e i f S u c c e s s , N o n e i f F a i l u r e
  41. SCALA.UTIL.CONTROL._ 1. Utility methods for common exception handling patterns 2.

    Less boiler plate than t r y / c a t c h / f i n a l l y
  42. SCALA.UTIL.CONTROL._ CATCHING AN EXCEPTION It returns C a t c

    h [ T ] c a t c h i n g ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) { i n p u t . t o I n t } / / R e t u r n s C a t c h [ I n t ]
  43. SCALA.UTIL.CONTROL._ CONVERTING Converting to `Option Converting to E i t

    h e r Converting to T r y c a t c h i n g ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) . o p t { i n p u t . t o I n t } / / R e t u r n s O p t i o n [ I n t ] f a i l i n g ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) { i n p u t . t o I n t } / / R e t u r n s O p t i o n [ I n t ] c a t c h i n g ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) . e i t h e r { i n p u t . t o I n t } / / R e t u r n s E i t h e r [ T h r o w a b l e , I n t ] c a t c h i n g ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) . w i t h T r y { i n p u t . t o I n t } / / R e t u r n s T r y [ I n t ]
  44. SCALA.UTIL.CONTROL._ SIDE-EFFECTING i g n o r i n g

    ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) { p r i n t l n ( i n p u t . t o I n t ) } / / R e t u r n s C a t c h [ U n i t ]
  45. SCALA.UTIL.CONTROL._ CATCHING NON-FATAL EXCEPTIONS What are non-fatal exceptions? All instead

    of: V i r t u a l M a c h i n e E r r o r , T h r e a d D e a t h , I n t e r r u p t e d E x c e p t i o n , L i n k a g e E r r o r , C o n t r o l T h r o w a b l e , N o t I m p l e m e n t e d E r r o r n o n F a t a l C a t c h { p r i n t l n ( i n p u t . t o I n t ) }
  46. SCALA.UTIL.CONTROL._ PROVIDING DEFAULT VALUE v a l a g e

    = f a i l A s V a l u e ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) ( 0 ) { i n p u t . t o I n t }
  47. SCALA.UTIL.CONTROL._ WHAT ABOUT FINALLY With catch logic No catch logic

    c a t c h i n g ( c l a s s O f [ N u m b e r F o r m a t E x c e p t i o n ] ) . a n d F i n a l l y { p r i n t l n ( " A g e p a r s e d s o m e h o w " ) } . a p p l y { i n p u t . t o I n t } u l t i m a t e l y ( p r i n t l n ( " A g e p a r s e d s o m e h o w " ) ) { i n p u t . t o I n t }