我正在尝试使用部分函数进行一些验证,让我们举一个字符串示例:
for i,row in df.iterrows():
print(row['year'], "- adding ",row['title'])
try:
request.urlretrieve(row['pdfarticle'],"_tmp.pdf")
except http.client.RemoteDisconnected:
continue # this will skip the url throwing error
预期输出=> Some(“有效”)
但是我遇到了匹配错误:
scala.MatchError:有效(属于类java.lang.String)
任何人都可以帮助解决这里的问题,因为据我了解, .isDefinedAt 是在内部调用的,因此不应给出 matchError 。
PS忽略输入,这只是一个例子。
答案 0 :(得分:5)
您的理解是错误的。 ScalaDocs page明确指出:“在呼叫isDefinedAt
之前,呼叫者有责任呼叫apply
...”。
您的代码未调用isDefinedAt
,这会导致异常,因此您必须显式调用它,或者可以使用其他方法在内部隐藏isDefinedAt
。
Seq("valid") collect (isLengthValid orElse isStringValid)
//res0: Seq[Option[String]] = List(Some(Valid))
Seq("vlad") collect (isLengthValid orElse isStringValid)
//res1: Seq[Option[String]] = List()
答案 1 :(得分:4)
如果您将最后一行写为
,这将按预期工作Delete
我怀疑问题是您的版本降低了
(isLengthValid orElse isStringValid)("valid")
这意味着(isLengthValid.apply("valid")).orElse(isStringValid.apply("valid"))
是在apply
发生之前计算出来的,这意味着部分函数被视为总函数,并且如Valy Dia的答案所解释的,会抛出匹配错误。实际上在结果输出上调用orElse
,而不是部分函数。
答案 2 :(得分:1)
错误消息来自第一个表达式-isLengthValid
。
仅针对长度严格大于5的string
进行定义。因此,将其应用于长度为5的字符串"valid"
时,它将抛出MatchError
:>
scala>"valid".length
res5: Int = 5
isLengthValid("valid")
scala.MatchError: valid (of class java.lang.String)
如果方法isLengthValid
以此方式定义(注意大于等号),则不会抛出MatchError
:
def isLengthValid: PartialFunction[String, Option[String]] ={
case s:String if s.length >= 5 => Some("Invalid")
}
scala>isLengthValid("valid")
res8: Option[String] = Some("Invalid")
原始表达式将返回Option
:
scala>isLengthValid("valid") orElse isStringValid("valid")
res9: Option[String] = Some("Invalid")
您可以在此处进行操作以及对此question进行说明,而是改用此定义:
val isLengthValid = new PartialFunction[String, Option[String]] {
def isDefinedAt(x: String) = x.length > 5
def apply(x: String) = Some("Invalid")
}
scala>isLengthValid("valid")
res13: Some[String] = Some("Invalid")