8

有没有办法通过语句创建一个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两次。

4

5 回答 5

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 来测试它是否有效,然后在函数应用程序中创建大 int再次...

我在Github上看到了一个项目,它试图通过缓存isDefinedAt. 如果你去基准测试,你会发现它比默认的 Scala 实现要慢:)

因此,如果您想绕过isDefinedAtvs的双重性质apply,您应该直接使用提供Option[Int]as 结果的(完整)函数。

于 2011-04-14T19:37:58.307 回答
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 的信息:

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)
于 2011-11-15T02:35:19.047 回答
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")
}
于 2011-04-15T00:36:54.127 回答
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
  }
}
于 2012-03-06T16:34:44.897 回答
0

这个怎么样?

val toInt: PartialFunction[String, Int] = (s: String) => BigInt(s) match {
  case bi if bi.isValidInt => bi.intValue
}
于 2011-09-15T19:12:47.000 回答