在模式匹配部分函数中,如何使 isDefined 为无法包含在大小写模式中的无效输入返回 false?



在用模式匹配实现的分部函数中,如何使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)评估为NoneadecodeList.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编译器默认提供的类型不同。

最新更新