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
Failures 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
Failureobject if it isEmpty(with the?~orfailMsgmethod). - You can chain failure messages on
Failures (with the?~!orcompoundFailMsgmethod). - 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
Boxto 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 Exceptions 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
forcomprehension, 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(forcomprehensions 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
Failures):
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
Boxplay better with Scalaforcomprehensions.
Abstract Value Members
-
abstract
def
canEqual(that: Any): Boolean
- Definition Classes
- Equals
-
abstract
def
isEmpty: Boolean
Returns
trueif thisBoxcontains no value (i.e., it isEmptyorFailureorParamFailure). -
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
Boxif it isFull.
- Exceptions thrown
NullPointerExceptionIf you attempt to call it on anEmptyBox, with a message that includes the providedjustification.
-
abstract
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. -
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
Emptyto aFailurewith the specified message.Transform an
Emptyto aFailurewith the specified message. Otherwise returns the same box.- returns
A
Failurewith the message if thisBoxisEmpty, this box otherwise.
- Note
This means a
Failurewill also remain unchanged; see?~!to change these.
-
def
?~!(msg: ⇒ String): Box[A]
Chain the given
msgas aFailureahead of any failures thisBoxmay represent.Chain the given
msgas aFailureahead of any failures thisBoxmay represent.If this is an
Empty, this method behaves like?~. If it is aFailure, however, this method returns a newFailurewith the givenmsgand with itschainset to thisFailure.As with
?~, if this is aFull, we return it unchanged.- returns
A
Failurewith the message if thisBoxis anEmptybox. Chain this box to the newFailureif this is aFailure. The unchanged box if it is aFull.
-
def
asA[B](implicit m: Manifest[B]): Box[B]
Create a
Fullbox containing the specified value if this box's value is of typeBandEmptyotherwise.Create a
Fullbox containing the specified value if this box's value is of typeBandEmptyotherwise.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[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()
-
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
Boxis 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
Iteratorover the value contained in thisBox, if any. -
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(other: Any): Boolean
For
FullandEmpty, this has the expected behavior.For
FullandEmpty, 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
Boxinstead 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
Boxcontains a value and it satisfies the specifiedfunc, returntrue.If this
Boxcontains a value and it satisfies the specifiedfunc, returntrue. Otherwise, returnfalse.- returns
trueif 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
Boxcontains a value and it satisfies the specifiedpredicate, return theBoxunchanged.If this
Boxcontains a value and it satisfies the specifiedpredicate, return theBoxunchanged. Otherwise, return anEmpty. -
def
filterMsg(msg: String)(p: (A) ⇒ Boolean): Box[A]
If this
Boxcontains a value and it satisfies the specifiedpredicate, return theBoxunchanged.If this
Boxcontains a value and it satisfies the specifiedpredicate, return theBoxunchanged. Otherwise, return aFailurewith the givenmsg.- returns
A
Failurewith 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
Boxcontains a value and it does not satisfy the specifiedf, return theBoxunchanged.If this
Boxcontains a value and it does not satisfy the specifiedf, return theBoxunchanged. Otherwise, return anEmpty. -
def
finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
def
flatMap[B](f: (A) ⇒ Box[B]): Box[B]
Apply a function returning a
Boxto the value contained in thisBoxif it exists and return the resultingBox.Apply a function returning a
Boxto the value contained in thisBoxif it exists and return the resultingBox. If thisBoxis not alreadyFull, return this box unchanged.- Note
This means that using
flatMapwith aFailurewill preserve theFailure.
- def flatten[B](implicit ev: <:<[A, Box[B]]): Box[B]
-
def
flip[B](flipFn: (EmptyBox) ⇒ B): Box[B]
Returns a
Fullbox containing the results of applyingflipFnto this box if it is aFailure,ParamFailureorEmpty.Returns a
Fullbox containing the results of applyingflipFnto this box if it is aFailure,ParamFailureorEmpty. ReturnsEmptyif this box isFull. In other words, it "flips" the full/empty status of this Box. -
def
forall(func: (A) ⇒ Boolean): Boolean
If this
Boxcontains a value and it does not satisfy the specifiedfunc, returnfalse.If this
Boxcontains a value and it does not satisfy the specifiedfunc, returnfalse. Otherwise, returntrue.- returns
true If the
Boxis 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
Boxis empty. -
def
fullXform[T](v: T)(f: (T) ⇒ (A) ⇒ T): T
If the
BoxisFull, apply the transform functionfon the valuev; otherwise, just return the value untransformed.If the
BoxisFull, apply the transform functionfon the valuev; otherwise, just return the value untransformed.The transform function is expected to be a function that will take the value
vand 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
BoxisFull, the value once transformed by the function returned byf. Otherwise, the initial valuev.
-
final
def
get: DoNotCallThisMethod
Exists to avoid the implicit conversion from
BoxtoOption.Exists to avoid the implicit conversion from
BoxtoOption. Opening aBoxunsafely should be done usingopenOrThrowException.This method always throws an exception.
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
isA[B](cls: Class[B]): Box[B]
If this box is
Fulland contains an object of typeB, returns aFullof typeBox[B].If this box is
Fulland contains an object of typeB, returns aFullof 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
Iteratorover the value contained in thisBox, if any. -
def
javaIterator[B >: A]: Iterator[B]
Get a
java.util.Iteratorfrom the Box. -
def
map[B](f: (A) ⇒ B): Box[B]
Apply a function to the value contained in this
Boxif it exists and return aFullcontaining the result.Apply a function to the value contained in this
Boxif it exists and return aFullcontaining the result. If thisBoxis not alreadyFull, return the unchanged box.- Note
This means that using
mapwith aFailurewill preserve theFailure.
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
def
openOr[B >: A](default: ⇒ B): B
Return the value contained in this
Boxif it is full; otherwise return the specified default.Return the value contained in this
Boxif it is full; otherwise return the specified default. Equivalent toOption'sgetOrElse. -
def
pass(f: (Box[A]) ⇒ Unit): Box[A]
Perform a side effect by passing this
Boxto the specified function and return thisBoxunmodified.Perform a side effect by passing this
Boxto the specified function and return thisBoxunmodified. Similar toforeach, except thatforeachreturnsUnit, 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
invalue and the value contained in thisBox.This method calls the specified function with the specified
invalue and the value contained in thisBox. If this box is empty, returns theinvalue directly.- returns
The result of the function or the
invalue.
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toLeft[B](right: ⇒ B): Either[A, B]
An
Eitherthat is aRightwith the given argumentrightif this is empty, or aLeftwith the boxed value if this isFull. -
def
toList: List[A]
Returns a
Listof one element if this is Full, or an empty list if empty. -
def
toOption: Option[A]
Returns the contents of this box wrapped in
Someif this isFull, orNoneif this is empty (meaning anEmpty,Failureor ParamFailure). -
def
toRight[B](left: ⇒ B): Either[B, A]
An
Eitherthat is aLeftwith the given argumentleftif this is empty, or aRightwith the boxed value if this isFull. -
def
toString(): String
- Definition Classes
- AnyRef → Any
-
def
transform[B >: A](transformFn: PartialFunction[Box[A], Box[B]]): Box[B]
Transforms this box using the
transformFn.Transforms this box using the
transformFn. IftransformFnis defined for this box, returns the result of applyingtransformFnto it. Otherwise, returns this box unchanged.If you want to change the content of a
Fullbox, usingmaporcollectmight be better suited to that purpose. If you want to convert anEmpty,Failureor aParamFailureinto aFullbox, you should useflip.// Returns Full("alternative") because the partial function covers the case. Full("error") transform { case Full("error") => Full("alternative") } // Returns Full(1), this Full box unchanged, because the partial function doesn't cover the case. Full(1) transform { case Full(2) => Failure("error") } // Returns this Failure("another-error") unchanged because the partial function doesn't cover the case. Failure("another-error") transform { case Failure("error", Empty, Empty) => Full("alternative") } // Returns Full("alternative") for an Empty box since `partialFn` is defined for Empty Empty transform { case Empty => Full("alternative") } // Returns Empty because the partial function is not defined for Empty Empty transform { case Failure("error", Empty, Empty) => Full("alternative") }
Example: -
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( ... ) @native()
-
def
withFilter(p: (A) ⇒ Boolean): WithFilter
Makes
Boxplay better with Scalaforcomprehensions. -
def
~>[T](errorCode: ⇒ T): Box[A]
Transform an
EmptyorFailureto aParamFailurewith the specified type-safe parameter.Transform an
EmptyorFailureto aParamFailurewith the specified type-safe parameter.- errorCode
A value indicating the error.
- returns
A
ParamFailurewith the specified value, unless this is already aParamFailureor aFull. If this is aFailure, theParamFailurewill preserve the message of theFailure.