Skip to content

Commit

Permalink
Merge pull request #1165 from jsuereth/fix/try-catch-libs
Browse files Browse the repository at this point in the history
Fix/try catch libs
  • Loading branch information
jsuereth committed Aug 20, 2012
2 parents c51d0a8 + 2450220 commit ef6f005
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 27 deletions.
43 changes: 16 additions & 27 deletions src/library/scala/util/control/Exception.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
** |/ **
\* */

package scala.util.control
package scala.util
package control

import collection.immutable.List
import reflect.{ ClassTag, classTag }
Expand All @@ -25,6 +26,10 @@ import language.implicitConversions
* val x2 = catching(classOf[MalformedURLException], classOf[NullPointerException]) either new URL(s)
* }}}
*
* This class differs from `scala.util.Try` in that it focuses on composing exception handlers rather than
* composing behavior. All behavior should be composed first and fed to a `Catch` object using one of the
* `opt` or `either` methods.
*
* @author Paul Phillips
*/

Expand Down Expand Up @@ -118,6 +123,11 @@ object Exception {
*/
def either[U >: T](body: => U): Either[Throwable, U] = toEither(Right(body))

/** Apply this catch logic to the supplied body, mapping the result
* into Try[T] - Failure if an exception was caught, Success(T) otherwise.
*/
def withTry[U >: T](body: => U): scala.util.Try[U] = toTry(Success(body))

/** Create a `Catch` object with the same `isDefinedAt` logic as this one,
* but with the supplied `apply` method replacing the current one. */
def withApply[U](f: Throwable => U): Catch[U] = {
Expand All @@ -131,35 +141,11 @@ object Exception {
/** Convenience methods. */
def toOption: Catch[Option[T]] = withApply(_ => None)
def toEither: Catch[Either[Throwable, T]] = withApply(Left(_))
}

/** A container class for Try logic */
class Try[+T] private[Exception](body: => T, val catcher: Catch[T]) {
/** Execute "body" using catch/finally logic "catcher" */
def apply(): T = catcher(body)
def apply[U >: T](other: => U): U = catcher(other)

/** As apply, but map caught exceptions to `None` and success to `Some(T)`. */
def opt(): Option[T] = catcher opt body
def opt[U >: T](other: => U): Option[U] = catcher opt other

/** As apply, but map caught exceptions to `Left(ex)` and success to Right(x) */
def either(): Either[Throwable, T] = catcher either body
def either[U >: T](other: => U): Either[Throwable, U] = catcher either other

/** Create a `Try` object with the supplied body replacing the current body. */
def tryInstead[U >: T](other: => U) = new Try(other, catcher)

/** Create a `Try` object with the supplied logic appended to the existing Catch logic. */
def or[U >: T](pf: Catcher[U]) = new Try(body, catcher or pf)

/** Create a `Try`object with the supplied code appended to the existing `Finally`. */
def andFinally(fin: => Unit) = new Try(body, catcher andFinally fin)

override def toString() = List("Try(<body>)", catcher.toString) mkString " "
def toTry: Catch[scala.util.Try[T]] = withApply(x => Failure(x))
}

final val nothingCatcher: Catcher[Nothing] = mkThrowableCatcher(_ => false, throw _)
final def nonFatalCatcher[T]: Catcher[T] = mkThrowableCatcher({ case NonFatal(_) => false; case _ => true }, throw _)
final def allCatcher[T]: Catcher[T] = mkThrowableCatcher(_ => true, throw _)

/** The empty `Catch` object. */
Expand All @@ -168,6 +154,9 @@ object Exception {
/** A `Catch` object which catches everything. */
final def allCatch[T]: Catch[T] = new Catch(allCatcher[T]) withDesc "<everything>"

/** A `Catch` object witch catches non-fatal exceptions. */
final def nonFatalCatch[T]: Catch[T] = new Catch(nonFatalCatcher[T]) withDesc "<non-fatal>"

/** Creates a `Catch` object which will catch any of the supplied exceptions.
* Since the returned `Catch` object has no specific logic defined and will simply
* rethrow the exceptions it catches, you will typically want to call `opt` or
Expand Down
3 changes: 3 additions & 0 deletions test/files/run/try-catch-unify.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Failure(java.lang.NumberFormatException: For input string: "Hi")
Success(5.0)
O NOES
15 changes: 15 additions & 0 deletions test/files/run/try-catch-unify.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import util._

import control.Exception._

object Test {
def main(args: Array[String]): Unit = {
println(catching(classOf[NumberFormatException]) withTry ("Hi".toDouble))
println(catching(classOf[NumberFormatException]) withTry ("5".toDouble))
try {
catching(classOf[NumberFormatException]) withTry (sys.error("O NOES"))
} catch {
case t => println(t.getMessage)
}
}
}

0 comments on commit ef6f005

Please sign in to comment.