在用模式匹配实现的分部函数中,如何使isDefined
为不能包含在事例模式中的无效输入返回false
?
例如,我有以下decodeList
部分函数:
case class Arr(items: List[Json]) extends Json
def decode(data: Json): Option[A]
def decodeList: PartialFunction[Json, List[A]] = {
case Json.Arr(items) =>
val options = items map decode
if (options forall (_.isDefined)) options map (_.get)
else throw new Error // the partial function should be undefined here
}
我想以某种方式更改代码,以便decodeList.isDefinedAt
对无效输入求值为false。例如,对于decode(a)
评估为None
的a
,decodeList.isDefinedAt(Json.Arr(List(a)))
应该评估为false
。
或者从另一个角度来看,如果我试图在下面的代码中的case模式中包含条件,那么我应该把val options = items map decode
定义放在哪里,以便它可以被case模式和块重用?
def decodeList: PartialFunction[Json, List[A]] = {
case Json.Arr(items) if (options forall (_.isDefined)) =>
options map (_.get)
}
您可以通过定义自定义提取器对象来实现这一点,例如
object Options {
def unapply(items: List[Json]) = Some(items map decode)
}
def decodeList: PartialFunction[Json, List[A]] = {
case Json.Arr(Options(options)) if (options forall (_.isDefined)) =>
options map (_.get)
}
这不是特别方便,但我不知道更好的方法。
当然,我建议实际定义def decodeList(list: Json): Option[List[A]]
,它更适合decode
,不需要这样的变通方法;如果您需要CCD_ 14,则选择CCD_。
def decodeList(list: Json) = list match {
case Json.Arr(items) =>
val options = items map decode
if (options forall (_.isDefined)) Some(options map (_.get)) else None
case _ => None
}
从技术上讲,您可以像一样直接定义PartialFunction
来覆盖isDefinedAt
def decodeList: PartialFunction[Json, List[A]] = new PartialFunction[Json, List[A]] {
override def apply(json: Json): List[A] = json match {
case Json.Arr(items) =>
val options = items map decode
options map (_.get)
}
override def isDefinedAt(json: Json): Boolean = json match {
case Json.Arr(items) =>
val options = items map decode
options forall (_.isDefined)
}
}
然而,这与CCD_ 17编译器默认提供的类型不同。