【发布时间】:2013-11-30 23:43:04
【问题描述】:
我已经实现了一个 Play! 2 Scala 中的 QueryStringBindable 用于 Range 类型。范围由最小值或最大值或两者组成(浮点类型)。在我的 QueryBindable 实现中,我使用 internalBinder 将两个可能的参数 min 和 max 转换为 Option[Either[String, Float]],将它们组合成一个元组,对此进行模式匹配,最后返回一个 Option[Either[String,范围]]。这可行,但正如您在下面的代码中看到的那样,模式匹配非常冗长。在 Scala 中有更简洁的方法吗? 也许以某种方式利用高阶函数来获得相同的结果结构?
import play.api.mvc.QueryStringBindable
case class Range(min: Option[Float], max: Option[Float])
object Range {
implicit def rangeQueryStringBindable(implicit intBinder: QueryStringBindable[Float]) = new QueryStringBindable[Range] {
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, Range]] = {
val minOpt = intBinder.bind("min", params)
val maxOpt = intBinder.bind("max", params)
(minOpt, maxOpt) match {
case (None, None) => None
case (Some(Right(min)), Some(Right(max))) => Some(Right(Range(Some(min), Some(max))))
case (None, Some(Right(max))) => Some(Right(Range(None, Some(max))))
case (Some(Right(min)), None) => Some(Right(Range(Some(min), None)))
case (Some(Left(minError)), Some(Left(maxError))) => Some(Left(minError))
case (Some(Left(minError)), None) => Some(Left(minError))
case (None, Some(Left(maxError))) => Some(Left(maxError))
case (Some(Right(_)), Some(Left(maxError))) => Some(Left(maxError))
case (Some(Left(minError)), Some(Right(_))) => Some(Left(minError))
}
}
override def unbind(key: String, range: Range): String = {
(range.min, range.max) match {
case (Some(min), Some(max)) => intBinder.unbind("min", min) + "&" + intBinder.unbind("max", max)
case (Some(min), None) => intBinder.unbind("min", min)
case (None, Some(max)) => intBinder.unbind("max", max)
case (None, None) => throw new IllegalArgumentException("Range without values makes no sense")
}
}
}
}
【问题讨论】:
标签: scala playframework-2.0 pattern-matching