scala.util
Type members
Classlikes
A utility object to support command line parsing for @main methods
A utility object to support command line parsing for @main methods
DynamicVariables
provide a binding mechanism where the current
value is found through dynamic scope, but where access to the
variable itself is resolved through static scope.
DynamicVariables
provide a binding mechanism where the current
value is found through dynamic scope, but where access to the
variable itself is resolved through static scope.
The current value can be retrieved with the value method. New values
should be pushed using the withValue
method. Values pushed via
withValue
only stay valid while the withValue
's second argument, a
parameterless closure, executes. When the second argument finishes,
the variable reverts to the previous value.
someDynamicVariable.withValue(newValue) {
// ... code called in here that calls value ...
// ... will be given back the newValue ...
}
Each thread gets its own stack of bindings. When a
new thread is created, the DynamicVariable
gets a copy
of the stack of bindings from the parent thread, and
from then on the bindings for the new thread
are independent of those for the original thread.
Represents a value of one of two possible types (a disjoint union).
Represents a value of one of two possible types (a disjoint union).
An instance of Either
is an instance of either scala.util.Left or scala.util.Right.
A common use of Either
is as an alternative to scala.Option for dealing
with possibly missing values. In this usage, scala.None is replaced
with a scala.util.Left which can contain useful information.
scala.util.Right takes the place of scala.Some. Convention dictates
that Left
is used for failure and Right
is used for success.
For example, you could use Either[String, Int]
to indicate whether a
received input is a String
or an Int
.
import scala.io.StdIn._
val in = readLine("Type Either a string or an Int: ")
val result: Either[String,Int] =
try Right(in.toInt)
catch {
case e: NumberFormatException => Left(in)
}
result match {
case Right(x) => s"You passed me the Int: $x, which I will increment. $x + 1 = ${x+1}"
case Left(x) => s"You passed me the String: $x"
}
Either
is right-biased, which means that Right
is assumed to be the default case to
operate on. If it is Left
, operations like map
and flatMap
return the Left
value unchanged:
def doubled(i: Int) = i * 2
Right(42).map(doubled) // Right(84)
Left(42).map(doubled) // Left(42)
Since Either
defines the methods map
and flatMap
, it can also be used in for comprehensions:
val right1 = Right(1) : Right[Double, Int]
val right2 = Right(2)
val right3 = Right(3)
val left23 = Left(23.0) : Left[Double, Int]
val left42 = Left(42.0)
for {
x <- right1
y <- right2
z <- right3
} yield x + y + z // Right(6)
for {
x <- right1
y <- right2
z <- left23
} yield x + y + z // Left(23.0)
for {
x <- right1
y <- left23
z <- right2
} yield x + y + z // Left(23.0)
// Guard expressions are not supported:
for {
i <- right1
if i > 0
} yield i
// error: value withFilter is not a member of Right[Double,Int]
// Similarly, refutable patterns are not supported:
for (x: Int <- right1) yield x
// error: value withFilter is not a member of Right[Double,Int]
Since for
comprehensions use map
and flatMap
, the types
of function parameters used in the expression must be inferred.
These types are constrained by the Either
values. In particular,
because of right-biasing, Left
values may require an explicit
type argument for type parameter B
, the right value. Otherwise,
it might be inferred as Nothing
.
for {
x <- left23
y <- right1
z <- left42 // type at this position: Either[Double, Nothing]
} yield x + y + z
// ^
// error: ambiguous reference to overloaded definition,
// both method + in class Int of type (x: Char)Int
// and method + in class Int of type (x: Byte)Int
// match argument types (Nothing)
for (x <- right2 ; y <- left23) yield x + y // Left(23.0)
for (x <- right2 ; y <- left42) yield x + y // error
for {
x <- right1
y <- left42 // type at this position: Either[Double, Nothing]
z <- left23
} yield x + y + z
// Left(42.0), but unexpectedly a `Either[Double,String]`
- Companion
- object
A type class for types that admit numeric literals.
A type class for types that admit numeric literals.
- Companion
- object
The left side of the disjoint union, as opposed to the scala.util.Right side.
The left side of the disjoint union, as opposed to the scala.util.Right side.
A special class used to implement negation in implicit search.
A special class used to implement negation in implicit search.
Consider the problem of using implicit i1
for a query type D
if an implicit
for some other class C
is available, and using an implicit i2
if no implicit
value of type C
is available. If we do not want to prioritize i1
and i2
by
putting them in different traits we can instead define the following:
given i1: D(using ev: C) = ... given i2: D(using ev: NotGiven[C]) = ...
NotGiven
is treated specially in implicit search, similar to the way logical negation
is treated in Prolog: The implicit search for NotGiven[C]
succeeds if and only if the implicit
search for C
fails.
In Scala 2 this form of negation can be simulated by setting up a conditional
ambiguous implicit and an unconditional fallback, the way it is done with the
default
, amb1
and amb2
methods below. Due to the way these two methods are
defined, NotGiven
is also usable from Scala 2.
In Dotty, ambiguity is a global error, and therefore cannot be used to implement negation.
Instead, NotGiven
is treated natively in implicit search.
- Companion
- object
The object Random
offers a default implementation
of scala.util.Random and random-related convenience methods.
The object Random
offers a default implementation
of scala.util.Random and random-related convenience methods.
- Companion
- class
The right side of the disjoint union, as opposed to the scala.util.Left side.
The right side of the disjoint union, as opposed to the scala.util.Left side.
The Sorting
object provides convenience wrappers for java.util.Arrays.sort
.
The Sorting
object provides convenience wrappers for java.util.Arrays.sort
.
Methods that defer to java.util.Arrays.sort
say that they do or under what
conditions that they do.
Sorting
also implements a general-purpose quicksort and stable (merge) sort
for those cases where java.util.Arrays.sort
could only be used at the cost
of a large memory penalty. If performance rather than memory usage is the
primary concern, one may wish to find alternate strategies to use
java.util.Arrays.sort
directly e.g. by boxing primitives to use
a custom ordering on them.
Sorting
provides methods where you can provide a comparison function, or
can request a sort of items that are scala.math.Ordered or that
otherwise have an implicit or explicit scala.math.Ordering.
Note also that high-performance non-default sorts for numeric types are not provided. If this is required, it is advisable to investigate other libraries that cover this use case.
The Try
type represents a computation that may either result in an exception, or return a
successfully computed value.
The Try
type represents a computation that may either result in an exception, or return a
successfully computed value. It's similar to, but semantically different from the scala.util.Either type.
Instances of Try[T]
, are either an instance of scala.util.Success[T] or scala.util.Failure[T].
For example, Try
can be used to perform division on a user-defined input, without the need to do explicit
exception-handling in all of the places that an exception might occur.
Example:
import scala.io.StdIn
import scala.util.{Try, Success, Failure}
def divide: Try[Int] = {
val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt)
val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt)
val problem = dividend.flatMap(x => divisor.map(y => x/y))
problem match {
case Success(v) =>
println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)
Success(v)
case Failure(e) =>
println("You must've divided by zero or entered something that's not an Int. Try again!")
println("Info from the exception: " + e.getMessage)
divide
}
}
An important property of Try
shown in the above example is its ability to pipeline, or chain, operations,
catching exceptions along the way. The flatMap
and map
combinators in the above example each essentially
pass off either their successfully completed value, wrapped in the Success
type for it to be further operated
upon by the next combinator in the chain, or the exception wrapped in the Failure
type usually to be simply
passed on down the chain. Combinators such as recover
and recoverWith
are designed to provide some type of
default behavior in the case of failure.
Note: only non-fatal exceptions are caught by the combinators on Try
(see scala.util.control.NonFatal).
Serious system errors, on the other hand, will be thrown.
Note:: all Try combinators will catch exceptions and return failure unless otherwise specified in the documentation.
Try
comes to the Scala standard library after years of use as an integral part of Twitter's stack.
- Companion
- object
A utility for performing automatic resource management.
A utility for performing automatic resource management. It can be used to perform an operation using resources, after which it releases the resources in reverse order of their creation.
Usage
There are multiple ways to automatically manage resources with Using
. If you only need
to manage a single resource, the apply
method is easiest; it wraps the
resource opening, operation, and resource releasing in a Try
.
Example:
import java.io.{BufferedReader, FileReader}
import scala.util.{Try, Using}
val lines: Try[Seq[String]] =
Using(new BufferedReader(new FileReader("file.txt"))) { reader =>
Iterator.continually(reader.readLine()).takeWhile(_ != null).toSeq
}
If you need to manage multiple resources, Using.Manager
should
be used. It allows the managing of arbitrarily many resources, whose creation, use, and
release are all wrapped in a Try
.
Example:
import java.io.{BufferedReader, FileReader}
import scala.util.{Try, Using}
val lines: Try[Seq[String]] = Using.Manager { use =>
val r1 = use(new BufferedReader(new FileReader("file1.txt")))
val r2 = use(new BufferedReader(new FileReader("file2.txt")))
val r3 = use(new BufferedReader(new FileReader("file3.txt")))
val r4 = use(new BufferedReader(new FileReader("file4.txt")))
// use your resources here
def lines(reader: BufferedReader): Iterator[String] =
Iterator.continually(reader.readLine()).takeWhile(_ != null)
(lines(r1) ++ lines(r2) ++ lines(r3) ++ lines(r4)).toList
}
If you wish to avoid wrapping management and operations in a Try
, you can use
Using.resource
, which throws any exceptions that occur.
Example:
import java.io.{BufferedReader, FileReader}
import scala.util.Using
val lines: Seq[String] =
Using.resource(new BufferedReader(new FileReader("file.txt"))) { reader =>
Iterator.continually(reader.readLine()).takeWhile(_ != null).toSeq
}
Suppression Behavior
If two exceptions are thrown (e.g., by an operation and closing a resource),
one of them is re-thrown, and the other is
added to it as a suppressed exception.
If the two exceptions are of different 'severities' (see below), the one of a higher
severity is re-thrown, and the one of a lower severity is added to it as a suppressed
exception. If the two exceptions are of the same severity, the one thrown first is
re-thrown, and the one thrown second is added to it as a suppressed exception.
If an exception is a ControlThrowable
, or
if it does not support suppression (see
Throwable
's constructor with an enableSuppression
parameter),
an exception that would have been suppressed is instead discarded.
Exceptions are ranked from highest to lowest severity as follows:
java.lang.VirtualMachineError
java.lang.LinkageError
java.lang.InterruptedException
andjava.lang.ThreadDeath
fatal exceptions, excluding
scala.util.control.ControlThrowable
scala.util.control.ControlThrowable
all other exceptions
When more than two exceptions are thrown, the first two are combined and re-thrown as described above, and each successive exception thrown is combined as it is thrown.
Adds chaining methods tap
and pipe
to every type.
Adds chaining methods tap
and pipe
to every type. See ChainingOps.