sealed abstract class Box[+A] extends Product with Serializable
The Box
class is a container which is able to declare if it is Full
(containing a single non-null value) or EmptyBox
. An EmptyBox
,
or empty, can be the Empty
singleton, Failure
or
ParamFailure
. Failure
and ParamFailure
contain information about
why the Box
is empty including exception information, possibly chained
Failure
s and a String
message.
This serves a similar purpose to the Option
class from
Scala standard library but adds several features:
- You can transform it to a
Failure
object if it isEmpty
(with the?~
orfailMsg
method). - You can chain failure messages on
Failure
s (with the?~!
orcompoundFailMsg
method). - You can "run" a function on a
Box
, with a default to return if the box isEmpty
:
val littleTeddyBears: Box[Int] = Full(10) littleTeddyBears.run("and then there were none") { (default: String, teddyBears: Int) => s"$teddyBears little teddy bears" } // => 10 little teddy bears val updatedTeddyBears: Box[Int] = Empty littleTeddyBears.run("and then there were none") { (default: String, teddyBears: Int) => s"$teddyBears little teddy bears" } // => and then there were none
- You can "pass" a
Box
to a function for side effects:
val littleTeddyBears: Box[Int] = Full(10) doSomething( littleTeddyBears $ { teddyBears: Box[Int] => println("Are there any?") println(teddyBears openOr 0) } ) // doSomething gets a Box[Int] as well
Exceptions and Empty Box Handling
If you grew up on Java, you're used to Exception
s as part of your program
logic. The Scala philosophy and the Lift philosophy is that exceptions are
for exceptional conditions such as failure of an external resource (e.g.,
your database goes offline) rather than simply indicating that a parameter
wasn't supplied or couldn't be parsed.
Lift's Box
and Scala's Option
provide mechanisms for being explicit
about a value existing or not existing rather than relying on a reference
being not-null. However, extracting a value from a Box
should be done
correctly. Available options are:
- Using a
for
comprehension, especially for multiple boxes:
val loggedInUser: Box[User] = for { username <- possibleUsername password <- possiblePassword user <- User.find("username" -> username) if User.checkPassword(password, user.password) } yield { user }
- Using
map
,flatMap
,filter
, andforeach
(for
comprehensions use these under the covers):
val fullName: Box[String] = loggedInUser.map { user => user.name + " (" + user.nickname + ")" } val bestFriend: Box[User] = loggedInUser.flatMap { user => UserFriends.find(user.bestFriend.id) } val allowedUser: Box[User] = loggedInUser.filter(_.canAccess_?(currentPage)) fullName.foreach { name => logger.info(s"User $name is in the building.") }
- Using pattern-matching (a good way to deal with
Failure
s):
val loginMessage: String = loggedInUser match { case Full(user) => "Login successful!" case Failure(message, _, _) => s"Login failed: $message" case Empty => s"Unknown failure logging in." }
- For comparisons (e.g., in tests), use
==
and===
:
loggedInUser must_== Full(mockUser) (loggedInUser === mockUser) must beTrue
- Self Type
- Box[A]
- Alphabetic
- By Inheritance
- Box
- Serializable
- Serializable
- Product
- Equals
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
-
class
WithFilter
extends AnyRef
Makes
Box
play better with Scalafor
comprehensions.
Abstract Value Members
-
abstract
def
canEqual(that: Any): Boolean
- Definition Classes
- Equals
-
abstract
def
isEmpty: Boolean
Returns
true
if thisBox
contains no value (i.e., it isEmpty
orFailure
orParamFailure
). -
abstract
def
openOrThrowException(justification: ⇒ String): A
The only time when you should be using this method is if the value is guaranteed to be available based on a guard outside of the method.
The only time when you should be using this method is if the value is guaranteed to be available based on a guard outside of the method. In these cases, please provide that information in the justification
String
. For example,User.currentUser.openOrThrowException("This snippet is only used on pages where the user is logged in")
. For tests, use==
or===
instead. See the class documentation for more information.A valid justification for using this method should not be "I want my code to fail fast when I call it." Using exceptions in the core logic of your application should be strongly discouraged.
- justification
Justify why calling this method is okay and why it will not result in an exception being thrown. This serves both as mandatory documentation and as a very clear indication of what unexpected thing happened in the event you were wrong about the guard.
- returns
The contents of the
Box
if it isFull
.
- Exceptions thrown
NullPointerException
If you attempt to call it on anEmptyBox
, with a message that includes the providedjustification
.
-
abstract
def
productArity: Int
- Definition Classes
- Product
-
abstract
def
productElement(n: Int): Any
- Definition Classes
- Product
Concrete Value Members
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
def
$(f: (Box[A]) ⇒ Unit): Box[A]
Alias for
pass
. -
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
===[B >: A](to: B): Boolean
Returns true if the value contained in this box is equal to the specified value.
Returns true if the value contained in this box is equal to the specified value. This is the same thing that
==
does when it's handed a value that isn't aBox
, but using this is recommended because it's clearer that the behavior will be different than the usual expectation. -
def
?~(msg: ⇒ String): Box[A]
Transform an
Empty
to aFailure
with the specified message.Transform an
Empty
to aFailure
with the specified message. Otherwise returns the same box.- returns
A
Failure
with the message if thisBox
isEmpty
, this box otherwise.
- Note
This means a
Failure
will also remain unchanged; see?~!
to change these.
-
def
?~!(msg: ⇒ String): Box[A]
Chain the given
msg
as aFailure
ahead of any failures thisBox
may represent.Chain the given
msg
as aFailure
ahead of any failures thisBox
may represent.If this is an
Empty
, this method behaves like?~
. If it is aFailure
, however, this method returns a newFailure
with the givenmsg
and with itschain
set to thisFailure
.As with
?~
, if this is aFull
, we return it unchanged.- returns
A
Failure
with the message if thisBox
is anEmpty
box. Chain this box to the newFailure
if this is aFailure
. The unchanged box if it is aFull
.
-
def
asA[B](implicit m: Manifest[B]): Box[B]
Create a
Full
box containing the specified value if this box's value is of typeB
andEmpty
otherwise.Create a
Full
box containing the specified value if this box's value is of typeB
andEmpty
otherwise.For example:
scala> Full("boom").asA[Int] res0: net.liftweb.common.Box[Int] = Empty scala> Full(5).asA[Int] res1: net.liftweb.common.Box[Int] = Full(5)
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
choice[B](f1: (A) ⇒ Box[B])(alternative: ⇒ Box[B]): Box[B]
Equivalent to
flatMap(f1).or(alternative)
. -
def
clone(): AnyRef
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
collect[B](pf: PartialFunction[A, B]): Box[B]
If the partial function is defined at the current Box's value, apply the partial function.
-
final
def
collectFirst[B](pf: PartialFunction[A, B]): Box[B]
An alias for
collect
.An alias for
collect
.Although this function is different for true collections, because
Box
is really a collection of 1, the two functions are identical. -
def
compoundFailMsg(msg: ⇒ String): Box[A]
Alias for
?~!
. -
def
dmap[B](dflt: ⇒ B)(f: (A) ⇒ B): B
Equivalent to
map(f).openOr(dflt)
. -
def
elements: Iterator[A]
Returns an
Iterator
over the value contained in thisBox
, if any. -
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(other: Any): Boolean
For
Full
andEmpty
, this has the expected behavior.For
Full
andEmpty
, this has the expected behavior. Equality in terms of Failure checks for equivalence of failure causes:Failure("boom") == Failure("boom") Failure("bam") != Failure("boom") Failure("boom", Full(someException), Empty) != Failure("boom")
For other values, determines equality based upon the contents of this
Box
instead of the box itself. As a result, it is not symmetric. As an example:val foo = "foo" val boxedFoo = Full(foo) foo == boxedFoo //is false boxedFoo == foo //is true
It is safest to use
===
explicitly when you're looking for this behavior, and use==
only for box-to-box comparisons:Full("magic") == Full("magic") Full("magic") != Full("another") Full("magic") != Empty Full("magic") != Failure("something's gone wrong")
- Definition Classes
- Box → Equals → AnyRef → Any
-
def
exists(func: (A) ⇒ Boolean): Boolean
If this
Box
contains a value and it satisfies the specifiedfunc
, returntrue
.If this
Box
contains a value and it satisfies the specifiedfunc
, returntrue
. Otherwise, returnfalse
.- returns
true
if this Box does contain a value and it satisfies the predicate.
-
def
failMsg(msg: ⇒ String): Box[A]
Alias for
?~
. -
def
filter(p: (A) ⇒ Boolean): Box[A]
If this
Box
contains a value and it satisfies the specifiedpredicate
, return theBox
unchanged.If this
Box
contains a value and it satisfies the specifiedpredicate
, return theBox
unchanged. Otherwise, return anEmpty
. -
def
filterMsg(msg: String)(p: (A) ⇒ Boolean): Box[A]
If this
Box
contains a value and it satisfies the specifiedpredicate
, return theBox
unchanged.If this
Box
contains a value and it satisfies the specifiedpredicate
, return theBox
unchanged. Otherwise, return aFailure
with the givenmsg
.- returns
A
Failure
with the message if the box is empty or the predicate is not satisfied by the value contained in this Box.
- See also
-
def
filterNot(f: (A) ⇒ Boolean): Box[A]
If this
Box
contains a value and it does not satisfy the specifiedf
, return theBox
unchanged.If this
Box
contains a value and it does not satisfy the specifiedf
, return theBox
unchanged. Otherwise, return anEmpty
. -
def
finalize(): Unit
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
def
flatMap[B](f: (A) ⇒ Box[B]): Box[B]
Apply a function returning a
Box
to the value contained in thisBox
if it exists and return the resultingBox
.Apply a function returning a
Box
to the value contained in thisBox
if it exists and return the resultingBox
. If thisBox
is not alreadyFull
, return this box unchanged.- Note
This means that using
flatMap
with aFailure
will preserve theFailure.
- def flatten[B](implicit ev: <:<[A, Box[B]]): Box[B]
-
def
forall(func: (A) ⇒ Boolean): Boolean
If this
Box
contains a value and it does not satisfy the specifiedfunc
, returnfalse
.If this
Box
contains a value and it does not satisfy the specifiedfunc
, returnfalse
. Otherwise, returntrue
.- returns
true If the
Box
is empty, or if its value satisfies the predicate.
-
def
foreach[U](f: (A) ⇒ U): Unit
Perform a side effect by calling the specified function with the value contained in this box.
Perform a side effect by calling the specified function with the value contained in this box. The function does not run if this
Box
is empty. -
def
fullXform[T](v: T)(f: (T) ⇒ (A) ⇒ T): T
If the
Box
isFull
, apply the transform functionf
on the valuev
; otherwise, just return the value untransformed.If the
Box
isFull
, apply the transform functionf
on the valuev
; otherwise, just return the value untransformed.The transform function is expected to be a function that will take the value
v
and produce a function from the value in the box to a new value of the same type asv
.For example:
val myBox = Full(10) myBox.fullXForm("No teddy bears left.")({ message => { teddyBears: Int => s"$message Oh wait, there are $teddyBears left!" } })
- T
The type of the initial value, default value, and transformed value.
- returns
If the
Box
isFull
, the value once transformed by the function returned byf
. Otherwise, the initial valuev
.
-
final
def
get: DoNotCallThisMethod
Exists to avoid the implicit conversion from
Box
toOption
.Exists to avoid the implicit conversion from
Box
toOption
. Opening aBox
unsafely should be done usingopenOrThrowException
.This method always throws an exception.
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
-
def
isA[B](cls: Class[B]): Box[B]
If this box is
Full
and contains an object of typeB
, returns aFull
of typeBox[B]
.If this box is
Full
and contains an object of typeB
, returns aFull
of typeBox[B]
. Otherwise, returnsEmpty
.This is basically a Java-friendly version of
asA
, which you should prefer when using Scala.For example:
scala> Full("boom").isA(classOf[Int]) res0: net.liftweb.common.Box[Int] = Empty scala> Full(5).isA(classOf[Int]) res1: net.liftweb.common.Box[Int] = Full(5)
-
def
isDefined: Boolean
Returns true if the box contains a value.
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
def
iterator: Iterator[A]
Returns an
Iterator
over the value contained in thisBox
, if any. -
def
javaIterator[B >: A]: Iterator[B]
Get a
java.util.Iterator
from the Box. -
def
map[B](f: (A) ⇒ B): Box[B]
Apply a function to the value contained in this
Box
if it exists and return aFull
containing the result.Apply a function to the value contained in this
Box
if it exists and return aFull
containing the result. If thisBox
is not alreadyFull
, return the unchanged box.- Note
This means that using
map
with aFailure
will preserve theFailure.
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
-
def
openOr[B >: A](default: ⇒ B): B
Return the value contained in this
Box
if it is full; otherwise return the specified default.Return the value contained in this
Box
if it is full; otherwise return the specified default. Equivalent toOption
'sgetOrElse
. -
def
or[B >: A](alternative: ⇒ Box[B]): Box[B]
Return this Box if
Full
, or the specified alternative if it is empty.Return this Box if
Full
, or the specified alternative if it is empty. Equivalent toOption
'sorElse
. -
def
pass(f: (Box[A]) ⇒ Unit): Box[A]
Perform a side effect by passing this
Box
to the specified function and return thisBox
unmodified.Perform a side effect by passing this
Box
to the specified function and return thisBox
unmodified. Similar toforeach
, except thatforeach
returnsUnit
, while this method allows chained use of theBox
.- returns
This box.
-
def
productIterator: Iterator[Any]
- Definition Classes
- Product
-
def
productPrefix: String
- Definition Classes
- Product
-
def
run[T](in: ⇒ T)(f: (T, A) ⇒ T): T
This method calls the specified function with the specified
in
value and the value contained in thisBox
.This method calls the specified function with the specified
in
value and the value contained in thisBox
. If this box is empty, returns thein
value directly.- returns
The result of the function or the
in
value.
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toLeft[B](right: ⇒ B): Either[A, B]
An
Either
that is aRight
with the given argumentright
if this is empty, or aLeft
with the boxed value if this isFull
. -
def
toList: List[A]
Returns a
List
of one element if this is Full, or an empty list if empty. -
def
toOption: Option[A]
Returns the contents of this box wrapped in
Some
if this isFull
, orNone
if this is empty (meaning anEmpty
,Failure
or ParamFailure).
-
def
toRight[B](left: ⇒ B): Either[B, A]
An
Either
that is aLeft
with the given argumentleft
if this is empty, or aRight
with the boxed value if this isFull
. -
def
toString(): String
- Definition Classes
- AnyRef → Any
-
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
def
withFilter(p: (A) ⇒ Boolean): WithFilter
Makes
Box
play better with Scalafor
comprehensions. -
def
~>[T](errorCode: ⇒ T): Box[A]
Transform an
Empty
orFailure
to aParamFailure
with the specified type-safe parameter.Transform an
Empty
orFailure
to aParamFailure
with the specified type-safe parameter.- errorCode
A value indicating the error.
- returns
A
ParamFailure
with the specified value, unless this is already aParamFailure
or aFull
. If this is aFailure
, theParamFailure
will preserve the message of theFailure
.