【问题标题】:Why does Scala PartialFunction isDefinedAt method always return true?为什么Scala PartialFunction isDefinedAt 方法总是返回true?
【发布时间】:2020-03-31 23:37:43
【问题描述】:

我的代码如下。

    case class C[T]() {
      val pf:PartialFunction[Any,Any] = {
        case i:T => i
      }
    }

    println(C[Int]().pf.isDefinedAt(-1.0))

这会打印出true。为什么会这样?

【问题讨论】:

  • 由于擦除和其他事情永远不会奏效,你到底想做什么?
  • 我想要C[T] 像某种过滤器一样。它应该作为 C[Int]().pf.isDefinedAt(e) 工作。当e is of type Int时,应该返回true,否则返回false
  • 是的,我明白了,但你为什么要那个?更广泛的用例是什么?

标签: scala partialfunction


【解决方案1】:

由于类型擦除,您的代码基本上等于:

case class C[T]() {
  val pf:PartialFunction[Any,Any] = {
    case i:Any => i // this matches everything
  }
}

您可以使用TypeTags 来修复它:

import scala.reflect.runtime.universe._
case class C[T: TypeTag]() {
  def pf[U: TypeTag]: PartialFunction[U, Any] = {
    case i if typeOf[U] <:< typeOf[T] => i
  }
}

使用中:

@ C[Int]().pf.isDefinedAt("")
res41: Boolean = false

@ C[Int]().pf.isDefinedAt(34)
res42: Boolean = true

这些实际上等于

@ C[Int]().pf[String].isDefinedAt("")
res41: Boolean = false

@ C[Int]().pf[Int].isDefinedAt(34)
res42: Boolean = true

推断类型 U 的地方 - 它有一个限制,即当需要 TypeTag 时,它只能与编译器对类型的了解一样精确。

您也可以尝试使用ClassTag[T] 来使用运行时反射...但对于原语它会失败

case class C[T]()(implicit classTag: scala.reflect.ClassTag[T]) {
  def pf[U: TypeTag]: PartialFunction[U, Any] = {
    case i if classTag.runtimeClass.isInstance(i) => i
  }
}

导致

@ C[Int]().pf.isDefinedAt(34)
res2: Boolean = false

@ C[Int]().pf.isDefinedAt("")
res3: Boolean = false

问题是 classTag 会解析为 Scala 的 int 而运行时会显示 java.lang.Int

@ case class C[T]()(implicit classTag: scala.reflect.ClassTag[T]) {
    def pf: PartialFunction[Any, Any] = {
      case i => println(s"T = ${classTag.runtimeClass.getName}, here: ${i.getClass.getName}")
    }
  }
defined class C

@ C[Int]().pf.isDefinedAt(34)
res7: Boolean = true

@ C[Int]().pf(34)
T = int, here: java.lang.Integer
res8: Any = ()

一般来说这里没有完美的解决方案,你可以阅读更多类似的问题herehere

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 2020-01-29
    • 2012-04-03
    • 2021-09-11
    • 2015-05-12
    相关资源
    最近更新 更多