Reputation: 8821
I'm quite happy with working with Option type in Scala, and Lift's Box[T]
is great too.
But I'm little confused with how to dealing with Empty when it's a valid state.
For example, my program has three vals: title
, startDate
and endDate
, title
and startDate
are required field, but endDate
could be empty.
Now, I want get those data from database, so I wrapped them into Box[T]
, and in the following case, endDate
returned Empty
which means in database it is NULL
.
Now I want print those data on screen, so I've the following code, but it will not work because endDate
is Empty, so the body of for comprehension will not execute.
import net.liftweb.common._
object Main
{
val title: Box[String] = Full("title")
val startDate: Box[String] = Full("startDate")
val endDate: Box[String] = Empty
def main(args: Array[String]) {
for (title <- this.title; startDate <- this.startDate;
endDate <- this.endDate)
{
println("Title:" + title)
println("StartDate:" + startDate)
println("EndDate:" + endDate) // I hope now endDate = Empty or None
}
}
}
If I make endDate
as Box[Option[String]]
, it will works fine, but I feel it is a little ugly, because Box[String]
should be sufficient to denote that endDate
is NULL in database.
Upvotes: 1
Views: 653
Reputation: 24062
If you want to handle the case where endDate
is Empty
, then simply don't extract it.
for (title <- this.title; startDate <- this.startDate) {
println("Title:" + title)
println("StartDate:" + startDate)
println("EndDate:" + this.endDate) // this.endDate == Empty
}
Edit:
If you to handle failures, just add match..case
or if
tests.
this.endDate match {
case f: Failure =>
// handle failure
case endDate =>
for (title <- this.title; startDate <- this.startDate) {
println("Title:" + title)
println("StartDate:" + startDate)
println("EndDate:" + endDate) // endDate == Empty
}
}
Upvotes: 1
Reputation: 8821
Finally I come out with this implicit conversion and wrapper class:
class ValidEmptyBox[T](box: Box[T])
{
def validEmpty: Box[Box[T]] = box match {
case Full(x) => Full(Full(x))
case Empty => Full(Empty)
case Failure(msg, exception, chain) => Failure(msg, exception, chain)
}
}
object ValidEmptyBox {
implicit def toValidEmptyBox[T](box: Box[T]) = new ValidEmptyBox(box)
}
for(empty <- Empty.validEmpty) {
println(empty) // Empty
}
for(full <- Full("AA").validEmpty) {
println(full) // Full(AA)
}
for(fail <- Failure("Failure").validEmpty) {
println(fail) // No output
}
It seems works for me, but I will still like to know if there is a better way to do this.
Upvotes: 1