gpt4 book ai didi

Scala 转换为泛型类型(用于泛型数值函数)

转载 作者:行者123 更新时间:2023-12-03 16:07:01 26 4
gpt4 key购买 nike

我正在尝试实现一个包装数学 Java 函数的通用函数。为简单起见,我们可以假设 Java 函数 (Java 7) 接受一个参数并返回一个结果,两者都是 java.lang.Double 类型。当然,包装函数应该接受一个参数和一个结果,两者都是泛型但数字类型 A。问题是我无法在包装函数中将结果转换回类型 A。哪里/什么问题?

注意:(我是 Scala 的新手,使用以下引用来解决问题。)

  • 我正在使用隐式类型特征 Numeric 来强制模板类型是数字。 How do I implement a generic mathematical function in Scala
  • 我发现了“import scala.collection.JavaConversions._”,我不完全理解,但在我看来,它更适合转换 Java 集合,并不能解决我的问题,是吗? Iterating over Java collections in Scala
  • 如此处所述,我尝试使用 Manifest 来强制执行正确的强制转换(变体 B),但最终以异常 java.lang.ClassCastException 结束。 Scala asInstanceOf with parameterized types

  • 变体A
    package test

    object mytest {
    def f[A](x: A)(implicit num: Numeric[A]): A = {
    val result = new java.lang.Double(num.toDouble(x))
    result.asInstanceOf[A]
    }

    def main(args: Array[String]) {
    // 'Some code'
    }
    }

    '一些代码' A1
    result val result = f(3)

    输出:
    Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
    at test.mytest$.main(test.scala:10)
    at test.mytest.main(test.scala)

    '一些代码' A2
    println(f(3))

    输出:
    3.0

    '一些代码' A3
    println(f(3).getClass)

    输出:
    int

    变体B
    package test

    object mytest {
    def f[A : Manifest](x: A)(implicit num: Numeric[A]): A = {
    val result = new java.lang.Double(num.toDouble(x))
    manifest[A].erasure.cast(result).asInstanceOf[A]
    }

    def main(args: Array[String]) {
    val result = f(3)
    }
    }

    输出:

    (这对于变体 A1、A2 和 A3 的等效项也是相同的,因为异常现在在函数 f 的第 6 行中抛出。)
    Exception in thread "main" java.lang.ClassCastException: Cannot cast java.lang.Double to int
    at java.lang.Class.cast(Class.java:3176)
    at test.mytest$.f(test.scala:6)
    at test.mytest$.main(test.scala:10)
    at test.mytest.main(test.scala)

    最佳答案

    你不能投 DoubleInteger无论如何(因为它是盒装的)。 Numeric只允许您在 T 上进行一组数学运算(通过 import num._ ) - 没有别的(您不需要一些中介类型)。 A2 工作仅因为 println 期望 Any由于 f(3) ,所以 T自动推断为 Any ; println(f[Int](3))永远不会工作,f[Any](3)将永远工作。

    如果您想实现操作 Doubles 的通用函数(只有当您有特定于 Double 的操作时才需要它) - 您最好返回 Double。如果你不能 - 你将不得不通过分析 T 来手动构造类型:

    def f[A](x: A)(implicit num: Numeric[A]): A = {
    val result = new java.lang.Double(num.toDouble(x))
    (x match {
    case x: Double => result
    case x: Int => result.toInt
    case x: Float => result.toFloat
    case x: Long => result.toLong
    }).asInstanceOf[A]
    }

    做不到的原因 result.doubleValue.asInstanceOf[A]这是 A 已经装箱。 @specialized注释不适用于 asInstanceOf ( type A is still boxed )

    更新:实际上 @specialized作品:
    def f[@specialized(Int, Double, Long, Float) A](x: A)(implicit num: Numeric[A]): A = {
    val result = new java.lang.Double(num.toDouble(x))

    result.doubleValue.asInstanceOf[A]
    }

    但它 doesn't work in Scala REPL - 所以要小心!

    附言不推荐使用 list :使用 classTag/ typeTag反而

    关于Scala 转换为泛型类型(用于泛型数值函数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27212776/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com