scala.util.control

Type members

Classlikes

class Breaks

Provides the break control abstraction.

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)
}
Companion:
object
Source:
Breaks.scala
object Breaks extends Breaks

An object that can be used for the break control abstraction.

An object that can be used for the break control abstraction.

Example usage:

import Breaks.{break, breakable}

breakable {
  for (...) {
    if (...) break
  }
}
Companion:
class
Source:
Breaks.scala
abstract class ControlThrowable(message: String) extends Throwable

A parent class for throwable objects intended for flow control.

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:
ControlThrowable.scala
object Exception

Classes representing the components of exception handling.

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 = "https://www.scala-lang.org/"

// Some(https://www.scala-lang.org/)
val x1: Option[URL] = catching(classOf[MalformedURLException]) opt new URL(s)

// Right(https://www.scala-lang.org/)
val x2: Either[Throwable,URL] =
  catching(classOf[MalformedURLException], classOf[NullPointerException]) either new URL(s)

// Success(https://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 = "https://www.scala-lang.org/"
// Prints page content,
//   &lt;!DOCTYPE html&gt;
//   &lt;html&gt;
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(&lt;console&gt;: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 Catchs 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:
Exception.scala
trait NoStackTrace extends Throwable

A trait for exceptions which, for efficiency reasons, do not fill in the stack trace.

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.

Note:

Since JDK 1.7, a similar effect can be achieved with class Ex extends Throwable(..., writableStackTrace = false)

Companion:
object
Source:
NoStackTrace.scala
Companion:
class
Source:
NoStackTrace.scala
object NonFatal

Extractor of non-fatal Throwables.

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:
NonFatal.scala

Library implementation of nonlocal return.

Library implementation of nonlocal return.

Usage:

import scala.util.control.NonLocalReturns.*

returning { ... throwReturn(x) ... }

Source:
NonLocalReturns.scala
object TailCalls

Methods exported by this object implement tail calls via trampolining.

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" https://blog.higher-order.com/assets/trampolines.pdf

Here'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:
TailCalls.scala