1
+ /* __ *\
2
+ ** ________ ___ / / ___ Scala API **
3
+ ** / __/ __// _ | / / / _ | (c) 2008-2011, LAMP/EPFL **
4
+ ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5
+ ** /____/\___/_/ |_/____/_/ | | **
6
+ ** |/ **
7
+ \* */
8
+
9
+
10
+
11
+ package scala .util
12
+
13
+ /**
14
+ * The Try type represents a computation that may either result in an exception,
15
+ * or return a success value. It's analagous to the `Either` type.
16
+ *
17
+ */
18
+ sealed abstract class Try [+ T ] {
19
+ /**
20
+ * Returns true if the Try is a Failure, false otherwise.
21
+ */
22
+ def isFailure : Boolean
23
+
24
+ /**
25
+ * Returns true if the Try is a Success, false otherwise.
26
+ */
27
+ def isSuccess : Boolean
28
+
29
+ /**
30
+ * Returns the value from this Success or the given argument if this is a Failure.
31
+ */
32
+ def getOrElse [U >: T ](default : => U ) = if (isSuccess) apply() else default
33
+
34
+ /**
35
+ * Returns the value from this Success or throws the exception if this is a Failure
36
+ */
37
+ def apply (): T
38
+
39
+ /**
40
+ * Returns the value from this Success or throws the exception if this is a Failure.
41
+ * Alias for apply()
42
+ */
43
+ def get = apply()
44
+
45
+ /**
46
+ * Applies the given function f if this is a Result.
47
+ */
48
+ def foreach [U ](f : T => U ) { onSuccess(f) }
49
+
50
+ /**
51
+ * Returns the given function applied to the value from this Success or returns this if this is a Failure.
52
+ *
53
+ */
54
+ def flatMap [U ](f : T => Try [U ]): Try [U ]
55
+
56
+ /**
57
+ * Maps the given function to the value from this Success or returns this if this is a Failure
58
+ */
59
+ def map [U ](f : T => U ): Try [U ]
60
+
61
+ /**
62
+ * Converts this to a Failure if the predicate is not satisfied.
63
+ */
64
+ def filter (p : T => Boolean ): Try [T ]
65
+
66
+ /**
67
+ * Calls the exceptionHandler with the exception if this is a Failure. This is like flatMap for the exception.
68
+ */
69
+ def rescue [U >: T ](rescueException : PartialFunction [Throwable , Try [U ]]): Try [U ]
70
+
71
+ /**
72
+ * Calls the exceptionHandler with the exception if this is a Failure. This is like map for the exception.
73
+ */
74
+ def handle [U >: T ](rescueException : PartialFunction [Throwable , U ]): Try [U ]
75
+
76
+ /**
77
+ * Invoked only if the computation was successful.
78
+ */
79
+ def onSuccess [U ](f : T => U ): Try [T ]
80
+
81
+ /**
82
+ * Invoked only if the computation failed.
83
+ */
84
+ def onFailure [U ](rescueException : Throwable => U ): Try [T ]
85
+
86
+ /**
87
+ * Invoked regardless of whether the computation completed
88
+ * successfully or unsuccessfully. Implemented in terms of
89
+ * `respond` so that subclasses control evaluation order. Returns a
90
+ * chained `this` as in `respond`.
91
+ */
92
+ def ensure [U ](f : => U ): Try [T ] =
93
+ respond { _ => f }
94
+
95
+ /**
96
+ * Returns None if this is a Failure or a Some containing the value if this is a Success
97
+ */
98
+ def toOption = if (isSuccess) Some (apply()) else None
99
+
100
+ /**
101
+ * Invokes the given closure when the value is available. Returns
102
+ * another 'This[R]' that is guaranteed to be available only *after*
103
+ * 'k' has run. This enables the enforcement of invocation ordering.
104
+ *
105
+ * This is overridden by subclasses.
106
+ */
107
+ def respond [U ](k : Try [T ] => U ): Try [T ] = {
108
+ k(this )
109
+ this
110
+ }
111
+
112
+ /**
113
+ * Invokes the given transformation when the value is available,
114
+ * returning the transformed value. This method is like a combination
115
+ * of flatMap and rescue. This method is typically used for more
116
+ * imperative control-flow than flatMap/rescue which often exploits
117
+ * the Null Object Pattern.
118
+ *
119
+ * This is overridden by subclasses.
120
+ */
121
+ def transform [U ](f : Try [T ] => Try [U ]): Try [U ] =
122
+ f(this )
123
+
124
+ /**
125
+ * Returns the given function applied to the value from this Success or returns this if this is a Failure.
126
+ * Alias for flatMap
127
+ */
128
+ def andThen [U ](f : T => Try [U ]) = flatMap(f)
129
+
130
+ /**
131
+ * Transforms a nested Try, i.e., a Try of type `Try[Try[T]]`,
132
+ * into an un-nested Try, i.e., a Try of type `Try[T]`
133
+ */
134
+ def flatten [U ](implicit ev : T <:< Try [U ]): Try [U ]
135
+ }
136
+
137
+ final case class Failure [+ T ](e : Throwable ) extends Try [T ] {
138
+ def isFailure = true
139
+ def isSuccess = false
140
+ def rescue [U >: T ](rescueException : PartialFunction [Throwable , Try [U ]]): Try [U ] = {
141
+ try {
142
+ if (rescueException.isDefinedAt(e)) rescueException(e) else this
143
+ } catch {
144
+ case e2 => Failure (e2)
145
+ }
146
+ }
147
+ def apply (): T = throw e
148
+ def flatMap [U ](f : T => Try [U ]): Try [U ] = Failure [U ](e)
149
+ def flatten [U ](implicit ev : T <:< Try [U ]): Try [U ] = Failure [U ](e)
150
+ def map [U ](f : T => U ): Try [U ] = Failure [U ](e)
151
+ def filter (p : T => Boolean ): Try [T ] = this
152
+ def onFailure [U ](rescueException : Throwable => U ): Try [T ] = {
153
+ rescueException(e)
154
+ this
155
+ }
156
+ def onSuccess [U ](f : T => U ): Try [T ] = this
157
+ def handle [U >: T ](rescueException : PartialFunction [Throwable , U ]): Try [U ] =
158
+ if (rescueException.isDefinedAt(e)) {
159
+ Try (rescueException(e))
160
+ } else {
161
+ this
162
+ }
163
+ }
164
+
165
+ final case class Success [+ T ](r : T ) extends Try [T ] {
166
+ def isFailure = false
167
+ def isSuccess = true
168
+ def rescue [U >: T ](rescueException : PartialFunction [Throwable , Try [U ]]): Try [U ] = Success (r)
169
+ def apply () = r
170
+ def flatMap [U ](f : T => Try [U ]): Try [U ] =
171
+ try f(r)
172
+ catch {
173
+ case e => Failure (e)
174
+ }
175
+ def flatten [U ](implicit ev : T <:< Try [U ]): Try [U ] = r
176
+ def map [U ](f : T => U ): Try [U ] = Try [U ](f(r))
177
+ def filter (p : T => Boolean ): Try [T ] =
178
+ if (p(apply())) this
179
+ else Failure (new NoSuchElementException (" Predicate does not hold" ))
180
+ def onFailure [U ](rescueException : Throwable => U ): Try [T ] = this
181
+ def onSuccess [U ](f : T => U ): Try [T ] = {
182
+ f(r)
183
+ this
184
+ }
185
+ def handle [U >: T ](rescueException : PartialFunction [Throwable , U ]): Try [U ] = this
186
+ }
187
+
188
+ object Try {
189
+
190
+ def apply [T ](r : => T ): Try [T ] = {
191
+ try { Success (r) } catch {
192
+ case e => Failure (e)
193
+ }
194
+ }
195
+
196
+ }
0 commit comments