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 Failure object if it is Empty (with the ?~ or failMsg method).
  • You can chain failure messages on Failures (with the ?~! or compoundFailMsg method).
  • You can "run" a function on a Box, with a default to return if the box is Empty:
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 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 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, and foreach (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 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]
Linear Supertypes
Known Subclasses
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. Box
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Type Members

  1. class WithFilter extends AnyRef

    Makes Box play better with Scala for comprehensions.

Abstract Value Members

  1. abstract def canEqual(that: Any): Boolean
    Definition Classes
    Equals
  2. abstract def isEmpty: Boolean

    Returns true if this Box contains no value (i.e., it is Empty or Failure or ParamFailure).

  3. 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 is Full.

    Exceptions thrown

    NullPointerException If you attempt to call it on an EmptyBox, with a message that includes the provided justification.

  4. abstract def productArity: Int
    Definition Classes
    Product
  5. abstract def productElement(n: Int): Any
    Definition Classes
    Product

Concrete Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. def $(f: (Box[A]) ⇒ Unit): Box[A]

    Alias for pass.

  4. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  5. 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 a Box, but using this is recommended because it's clearer that the behavior will be different than the usual expectation.

  6. def ?~(msg: ⇒ String): Box[A]

    Transform an Empty to a Failure with the specified message.

    Transform an Empty to a Failure with the specified message. Otherwise returns the same box.

    returns

    A Failure with the message if this Box is Empty, this box otherwise.

    Note

    This means a Failure will also remain unchanged; see ?~! to change these.

  7. def ?~!(msg: ⇒ String): Box[A]

    Chain the given msg as a Failure ahead of any failures this Box may represent.

    Chain the given msg as a Failure ahead of any failures this Box may represent.

    If this is an Empty, this method behaves like ?~. If it is a Failure, however, this method returns a new Failure with the given msg and with its chain set to this Failure.

    As with ?~, if this is a Full, we return it unchanged.

    returns

    A Failure with the message if this Box is an Empty box. Chain this box to the new Failure if this is a Failure. The unchanged box if it is a Full.

  8. def asA[B](implicit m: Manifest[B]): Box[B]

    Create a Full box containing the specified value if this box's value is of type B and Empty otherwise.

    Create a Full box containing the specified value if this box's value is of type B and Empty 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)
  9. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  10. def choice[B](f1: (A) ⇒ Box[B])(alternative: ⇒ Box[B]): Box[B]

    Equivalent to flatMap(f1).or(alternative).

  11. def clone(): AnyRef
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  12. 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.

  13. 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.

  14. def compoundFailMsg(msg: ⇒ String): Box[A]

    Alias for ?~!.

  15. def dmap[B](dflt: ⇒ B)(f: (A) ⇒ B): B

    Equivalent to map(f).openOr(dflt).

  16. def elements: Iterator[A]

    Returns an Iterator over the value contained in this Box, if any.

  17. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  18. def equals(other: Any): Boolean

    For Full and Empty, this has the expected behavior.

    For Full and Empty, 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
  19. def exists(func: (A) ⇒ Boolean): Boolean

    If this Box contains a value and it satisfies the specified func, return true.

    If this Box contains a value and it satisfies the specified func, return true. Otherwise, return false.

    returns

    true if this Box does contain a value and it satisfies the predicate.

  20. def failMsg(msg: ⇒ String): Box[A]

    Alias for ?~.

  21. def filter(p: (A) ⇒ Boolean): Box[A]

    If this Box contains a value and it satisfies the specified predicate, return the Box unchanged.

    If this Box contains a value and it satisfies the specified predicate, return the Box unchanged. Otherwise, return an Empty.

  22. def filterMsg(msg: String)(p: (A) ⇒ Boolean): Box[A]

    If this Box contains a value and it satisfies the specified predicate, return the Box unchanged.

    If this Box contains a value and it satisfies the specified predicate, return the Box unchanged. Otherwise, return a Failure with the given msg.

    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

    filter

  23. def filterNot(f: (A) ⇒ Boolean): Box[A]

    If this Box contains a value and it does not satisfy the specified f, return the Box unchanged.

    If this Box contains a value and it does not satisfy the specified f, return the Box unchanged. Otherwise, return an Empty.

  24. def finalize(): Unit
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  25. def flatMap[B](f: (A) ⇒ Box[B]): Box[B]

    Apply a function returning a Box to the value contained in this Box if it exists and return the resulting Box.

    Apply a function returning a Box to the value contained in this Box if it exists and return the resulting Box. If this Box is not already Full, return this box unchanged.

    Note

    This means that using flatMap with a Failure will preserve the Failure.

  26. def flatten[B](implicit ev: <:<[A, Box[B]]): Box[B]
  27. def forall(func: (A) ⇒ Boolean): Boolean

    If this Box contains a value and it does not satisfy the specified func, return false.

    If this Box contains a value and it does not satisfy the specified func, return false. Otherwise, return true.

    returns

    true If the Box is empty, or if its value satisfies the predicate.

  28. 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.

  29. def fullXform[T](v: T)(f: (T) ⇒ (A) ⇒ T): T

    If the Box is Full, apply the transform function f on the value v; otherwise, just return the value untransformed.

    If the Box is Full, apply the transform function f on the value v; 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 as v.

    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 is Full, the value once transformed by the function returned by f. Otherwise, the initial value v.

  30. final def get: DoNotCallThisMethod

    Exists to avoid the implicit conversion from Box to Option.

    Exists to avoid the implicit conversion from Box to Option. Opening a Box unsafely should be done using openOrThrowException.

    This method always throws an exception.

  31. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
  32. def hashCode(): Int
    Definition Classes
    AnyRef → Any
  33. def isA[B](cls: Class[B]): Box[B]

    If this box is Full and contains an object of type B, returns a Full of type Box[B].

    If this box is Full and contains an object of type B, returns a Full of type Box[B]. Otherwise, returns Empty.

    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)
  34. def isDefined: Boolean

    Returns true if the box contains a value.

  35. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  36. def iterator: Iterator[A]

    Returns an Iterator over the value contained in this Box, if any.

    Returns an Iterator over the value contained in this Box, if any.

    Synonym for elements.

  37. def javaIterator[B >: A]: Iterator[B]

    Get a java.util.Iterator from the Box.

  38. def map[B](f: (A) ⇒ B): Box[B]

    Apply a function to the value contained in this Box if it exists and return a Full containing the result.

    Apply a function to the value contained in this Box if it exists and return a Full containing the result. If this Box is not already Full, return the unchanged box.

    Note

    This means that using map with a Failure will preserve the Failure.

  39. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  40. final def notify(): Unit
    Definition Classes
    AnyRef
  41. final def notifyAll(): Unit
    Definition Classes
    AnyRef
  42. 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 to Option's getOrElse.

  43. 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 to Option's orElse.

  44. def pass(f: (Box[A]) ⇒ Unit): Box[A]

    Perform a side effect by passing this Box to the specified function and return this Box unmodified.

    Perform a side effect by passing this Box to the specified function and return this Box unmodified. Similar to foreach, except that foreach returns Unit, while this method allows chained use of the Box.

    returns

    This box.

  45. def productIterator: Iterator[Any]
    Definition Classes
    Product
  46. def productPrefix: String
    Definition Classes
    Product
  47. 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 this Box.

    This method calls the specified function with the specified in value and the value contained in this Box. If this box is empty, returns the in value directly.

    returns

    The result of the function or the in value.

  48. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  49. def toLeft[B](right: ⇒ B): Either[A, B]

    An Either that is a Right with the given argument right if this is empty, or a Left with the boxed value if this is Full.

  50. def toList: List[A]

    Returns a List of one element if this is Full, or an empty list if empty.

  51. def toOption: Option[A]

    Returns the contents of this box wrapped in Some if this is Full, or None if this is empty (meaning an Empty, Failure or ParamFailure).

  52. def toRight[B](left: ⇒ B): Either[B, A]

    An Either that is a Left with the given argument left if this is empty, or a Right with the boxed value if this is Full.

  53. def toString(): String
    Definition Classes
    AnyRef → Any
  54. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  55. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  56. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  57. def withFilter(p: (A) ⇒ Boolean): WithFilter

    Makes Box play better with Scala for comprehensions.

  58. def ~>[T](errorCode: ⇒ T): Box[A]

    Transform an Empty or Failure to a ParamFailure with the specified type-safe parameter.

    Transform an Empty or Failure to a ParamFailure with the specified type-safe parameter.

    errorCode

    A value indicating the error.

    returns

    A ParamFailure with the specified value, unless this is already a ParamFailure or a Full. If this is a Failure, the ParamFailure will preserve the message of the Failure.

Inherited from Serializable

Inherited from Serializable

Inherited from Product

Inherited from Equals

Inherited from AnyRef

Inherited from Any

Ungrouped