scala.util.control
package scala.util.control
Type members
Classlikes
class Breaks
Provides the
break
control abstraction.The
break
method uses a ControlThrowable
to transfer
control up the stack to an enclosing breakable
.It is typically used to abruptly terminate a
for
loop,
but can be used to return from an arbitrary computation.Control resumes after the
breakable
.If there is no matching
breakable
, the BreakControl
thrown by break
is handled in the usual way: if not
caught, it may terminate the current Thread
.BreakControl
carries no stack trace, so the default
exception handler does not print useful diagnostic
information; there is no compile-time warning if there
is no matching breakable
.A catch clause using
NonFatal
is safe to use with
break
; it will not short-circuit the transfer
of control to the enclosing breakable
.A
breakable
matches a call to break
if the methods
were invoked on the same receiver object, which may be the
convenience value Breaks
.Example usage:
val mybreaks = new Breaks
import mybreaks.{break, breakable}
breakable {
for (x <- xs) {
if (done) break()
f(x)
}
}
Calls to
break
from one instance of Breaks
will never
resume at the breakable
of some other instance.Any intervening exception handlers should use
NonFatal
,
or use Try
for evaluation:val mybreaks = new Breaks
import mybreaks.{break, breakable}
breakable {
for (x <- xs) Try { if (quit) break else f(x) }.foreach(println)
}
A parent class for throwable objects intended for flow control.
Instances of
ControlThrowable
should not normally be caught.As a convenience,
NonFatal
does not match ControlThrowable
.import scala.util.control.{Breaks, NonFatal}, Breaks.{break, breakable}
breakable {
for (v <- values) {
try {
if (p(v)) break
else ???
} catch {
case NonFatal(t) => log(t) // can't catch a break
}
}
}
Suppression is disabled, because flow control should not suppress
an exceptional condition. Stack traces are also disabled, allowing
instances of
ControlThrowable
to be safely reused.Instances of
ControlThrowable
should not normally have a cause.
Legacy subclasses may set a cause using initCause
.
- Source
- (source)
object Exception
Classes representing the components of exception handling.
Each class is independently composable.
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
, either
or withTry
methods. Taken together the classes provide a DSL for composing catch and finally
behaviors.Examples
Create a
Catch
which handles specified exceptions.import scala.util.control.Exception._
import java.net._
val s = "http://www.scala-lang.org/"
// Some(http://www.scala-lang.org/)
val x1: Option[URL] = catching(classOf[MalformedURLException]) opt new URL(s)
// Right(http://www.scala-lang.org/)
val x2: Either[Throwable,URL] =
catching(classOf[MalformedURLException], classOf[NullPointerException]) either new URL(s)
// Success(http://www.scala-lang.org/)
val x3: Try[URL] = catching(classOf[MalformedURLException], classOf[NullPointerException]) withTry new URL(s)
val defaultUrl = new URL("http://example.com")
// URL(http://example.com) because htt/xx throws MalformedURLException
val x4: URL = failAsValue(classOf[MalformedURLException])(defaultUrl)(new URL("htt/xx"))
Create a
Catch
which logs exceptions using handling
and by
.def log(t: Throwable): Unit = t.printStackTrace
val withThrowableLogging: Catch[Unit] = handling(classOf[MalformedURLException]) by (log)
def printUrl(url: String) : Unit = {
val con = new URL(url) openConnection()
val source = scala.io.Source.fromInputStream(con.getInputStream())
source.getLines().foreach(println)
}
val badUrl = "htt/xx"
// Prints stacktrace,
// java.net.MalformedURLException: no protocol: htt/xx
// at java.net.URL.<init>(URL.java:586)
withThrowableLogging { printUrl(badUrl) }
val goodUrl = "http://www.scala-lang.org/"
// Prints page content,
// <!DOCTYPE html>
// <html>
withThrowableLogging { printUrl(goodUrl) }
Use
unwrapping
to create a Catch
that unwraps exceptions before rethrowing.class AppException(cause: Throwable) extends RuntimeException(cause)
val unwrappingCatch: Catch[Nothing] = unwrapping(classOf[AppException])
def calcResult: Int = throw new AppException(new NullPointerException)
// Throws NPE not AppException,
// java.lang.NullPointerException
// at .calcResult(<console>:17)
val result = unwrappingCatch(calcResult)
Use
failAsValue
to provide a default when a specified exception is caught.val inputDefaulting: Catch[Int] = failAsValue(classOf[NumberFormatException])(0)
val candidatePick = "seven" // scala.io.StdIn.readLine()
// Int = 0
val pick = inputDefaulting(candidatePick.toInt)
Compose multiple
Catch
s with or
to build a Catch
that provides default values varied by exception.val formatDefaulting: Catch[Int] = failAsValue(classOf[NumberFormatException])(0)
val nullDefaulting: Catch[Int] = failAsValue(classOf[NullPointerException])(-1)
val otherDefaulting: Catch[Int] = nonFatalCatch withApply(_ => -100)
val combinedDefaulting: Catch[Int] = formatDefaulting or nullDefaulting or otherDefaulting
def p(s: String): Int = s.length * s.toInt
// Int = 0
combinedDefaulting(p("tenty-nine"))
// Int = -1
combinedDefaulting(p(null: String))
// Int = -100
combinedDefaulting(throw new IllegalStateException)
// Int = 22
combinedDefaulting(p("11"))
- Source
- (source)
A trait for exceptions which, for efficiency reasons, do not
fill in the stack trace. Stack trace suppression can be disabled
on a global basis via a system property wrapper in
scala.sys.SystemProperties.
object NonFatal
Extractor of non-fatal Throwables. Will not match fatal errors like
VirtualMachineError
(for example, OutOfMemoryError
and StackOverflowError
, subclasses of VirtualMachineError
), ThreadDeath
,
LinkageError
, InterruptedException
, ControlThrowable
.Note that scala.util.control.ControlThrowable, an internal Throwable, is not matched by
NonFatal
(and would therefore be thrown).For example, all harmless Throwables can be caught by:
try {
// dangerous stuff
} catch {
case NonFatal(e) => log.error(e, "Something not that bad.")
// or
case e if NonFatal(e) => log.error(e, "Something not that bad.")
}
- Source
- (source)
object NonLocalReturns
Library implementation of nonlocal return.
Usage:
import scala.util.control.NonLocalReturns._
returning { ... throwReturn(x) ... }
- Source
- (source)
object TailCalls
Methods exported by this object implement tail calls via trampolining.
Tail calling methods have to return their result using
done
or call the
next method using tailcall
. Both return a TailRec
object. The result
of evaluating a tailcalling function can be retrieved from a Tailrec
value using method result
.
Implemented as described in "Stackless Scala with Free Monads"
http://blog.higher-order.com/assets/trampolines.pdfHere's a usage example:
import scala.util.control.TailCalls._
def isEven(xs: List[Int]): TailRec[Boolean] =
if (xs.isEmpty) done(true) else tailcall(isOdd(xs.tail))
def isOdd(xs: List[Int]): TailRec[Boolean] =
if (xs.isEmpty) done(false) else tailcall(isEven(xs.tail))
isEven((1 to 100000).toList).result
def fib(n: Int): TailRec[Int] =
if (n < 2) done(n) else for {
x <- tailcall(fib(n - 1))
y <- tailcall(fib(n - 2))
} yield x + y
fib(40).result
- Source
- (source)