除了PartialFunction
声明之外,有没有办法创建case
?
我很好奇,因为我想表达以下内容(scala pseudo ahead!)...
val bi = BigInt(_)
if (bi.isValidInt) bi.intValue
...作为部分功能,并且正在执行
val toInt : PartialFunction[String, Int] = {
case s if BigInt(s).isValidInt => BigInt(s).intValue
}
似乎是多余的,因为我创建了BigInt
两次。
答案 0 :(得分:5)
不确定我理解这个问题。但这是我的尝试:为什么不创建一个提取器?
object ValidBigInt {
def unapply(s: String): Option[Int] = {
val bi = BigInt(s)
if (bi.isValidInt) Some(bi.intValue) else None
}
}
val toInt: PartialFunction[String, Int] = {
case ValidBigInt(i) => i
}
另一个选项是(并且可以回答关于是否可以创建除PartialFunction
字面值之外的case
的问题:
val toInt = new PartialFunction[String, Int] {
def isDefinedAt(s: String) = BigInt(s).isValidInt
def apply(s: String) = BigInt(s).intValue
}
然而,由于部分函数的想法是它只是部分定义,最终你仍然会做多余的事情 - 你需要创建一个大的int来测试它是否有效,然后在你创建的函数应用程序中又是一个大的... ...
我在Github看到一个项目试图通过稍微缓存isDefinedAt
的结果来解决这个问题。如果你进入基准测试,你会发现它比默认的Scala实现要慢:)
因此,如果您想要绕过isDefinedAt
与apply
的双重性质,您应该直接选择一个提供Option[Int]
的(完整)函数。
答案 1 :(得分:4)
我认为你正在寻找升力/升力。 lift取一个部分函数并将其转换为一个返回Option的函数。 Unlift使用一个返回选项的参数来获取函数,并返回一个部分函数。
import scala.util.control.Exception._
scala> def fn(s: String) = catching(classOf[NumberFormatException]) opt {BigInt(s)}
fn: (s: String)Option[scala.math.BigInt]
scala> val fnPf = Function.unlift(fn)
fnPf: PartialFunction[String,scala.math.BigInt] = <function1>
scala> val fn = fnPf.lift
fn: String => Option[scala.math.BigInt] = <function1>
密切相关,您还希望查看有关cond和condOpt的信息at this answer:
scala> import PartialFunction._
import PartialFunction._
scala> cond("abc") { case "def" => true }
res0: Boolean = false
scala> condOpt("abc") { case x if x.length == 3 => x + x }
res1: Option[java.lang.String] = Some(abcabc)
答案 2 :(得分:3)
如果您愿意,可以写出PartialFunction
“手写”:
object pf extends PartialFunction[Int,String] {
def isDefinedAt(in: Int) = in % 2 == 0
def apply(in: Int) = {
if (in % 2 == 0)
"even"
else
throw new MatchError(in + " is odd")
}
答案 3 :(得分:1)
好的,我得到了这个
import java.lang.NumberFormatException
import scala.util.control.Exception._
val toInt: PartialFunction[String, Int] = {
catching(classOf[NumberFormatException]) opt BigInt(_) match {
case Some(bi) if bi.isValidInt => bi.intValue
}
}
答案 4 :(得分:0)
这个怎么样?
val toInt: PartialFunction[String, Int] = (s: String) => BigInt(s) match {
case bi if bi.isValidInt => bi.intValue
}