将任意函数X => Y转换为X =>是多么不安全?斯卡拉单位?

时间:2017-03-01 02:31:36

标签: scala type-erasure

更明确地说,此代码可以在任何scenrios中产生任何错误:

def foreach[U](f :Int=>U) = f.asInstanceOf[Int=>Unit](1)

我知道它有效,而且我有一个模糊的想法:为任何函数,作为泛型类型的实例,必须定义apply的擦除版本,并且jvm仅在对象实际上执行时执行类型检查返回到具有混凝土类型的代码(通常在数英里之外)。所以,从理论上讲,只要我从不查看返回值,我就应该是安全的。我对Java字节代码没有足够的低级理解,更不用说scalac,对它有任何确定性。

我为什么要这样做?请看以下示例:

val b = new mutable.Buffer[Int]
val ints = Seq(1, 2, 3, 4)
ints foreach { b += _ }

这是典型的scala结构,只要命令式风格可以是典型的。此示例中的foreachInt作为参数,并且scalac知道它是Int,它将创建一个具有专门apply(x :Int)的闭包。不幸的是,在这种情况下,它的返回类型是mutable.Buffer[Int],它是AnyRef。据我所知,如果结果为scalacapply将永远不会调用提供AnyVal参数的专用AnyRef(反之亦然)。这意味着,即使调用者将函数应用于Int,函数下方也会对参数进行装箱并调用已擦除的变量。这当然无关紧要,因为无论如何它们都在List内,但我正在谈论这个原则。

出于这个原因,我更喜欢将此类方法定义为foreach(f :X=>Unit),而不是foreach[O](f: X=>O)中的TraversableOnce。如果示例中的输入序列具有这样的签名,则所有内容都将编译得很好,编译器将忽略表达式的实际类型并生成具有Unit返回类型的函数,该函数应用于未装箱时Int - 直接调用void apply(Int x),无需拳击。

问题出现在互操作性上 - 有时我需要调用一个期望具有Unit返回类型的函数的方法,而我所拥有的只是一个泛型函数,返回Odin知道什么。当然,我可以写f(_)将它放在另一个函数对象中而不是直接传递它,但它在很大程度上使得小紧环的整个优化没有实际意义。

0 个答案:

没有答案