为什么在Scala的标准库中专门有这么几件事?

我已经在Scala 2.8.1的标准库的源代码中search了@specialized的用法。 它看起来只有less数的特征和类使用这个注释: Function0Function1Function2Tuple1Tuple2Product1Product2AbstractFunction0AbstractFunction1AbstractFunction2

没有任何集合类是@specialized 。 为什么不? 这会产生太多类吗?

这意味着使用具有原始types的集合类是非常低效的,因为会有大量不必要的装箱和拆箱操作。

什么是最有效的方法来有一个不变的列表或序列(与IndexedSeq特性)的Int ,避免装箱和拆箱?

专业化对class级规模的成本很高,因此必须加以慎重考虑。 在collections品的特殊情况下,我认为这种影响将是巨大的。

不过,这是一个持续的努力 – 斯卡拉图书馆几乎没有开始专业化。

在类的大小和编译时间方面,专门化可能是昂贵的( 指数的 )。 它不只是接受的答案的大小说。

打开你的Scala REPL并input这个。

 import scala.{specialized => sp} trait S1[@sp A, @sp B, @sp C, @sp D] { def f(p1:A): Unit } 

对不起:-) 它就像一个编译器炸弹。

现在,让我们拿一个简单的特质

 trait Foo[Int]{ } 

以上将导致两个编译类。 Foo,纯粹的接口和Foo $ 1,类的实现。

现在,

 trait Foo[@specialized A] { } 

一个专门的模板参数在这里被扩展/重写了9种不同的基本types(void,boolean,byte,char,int,long,short,double,float)。 所以,基本上你最终会有20个class,而不是2个。

回到具有5个特定模板参数的特征,为每种可能的基元types的组合生成类。 即其复杂度指数。

2 * 10 ^ (没有专门的参数)

如果你正在为一个特定的基本types定义一个类,你应该更加明确的如

 trait Foo[@specialized(Int) A, @specialized(Int,Double) B] { } 

可以理解的是,在构build通用库时,必须要使用专门的节约。

保罗·菲利普斯咆哮着。

部分回答我自己的问题:我可以像这样在一个IndexedSeq包装一个数组:

 import scala.collection.immutable.IndexedSeq def arrayToIndexedSeq[@specialized(Int) T](array: Array[T]): IndexedSeq[T] = new IndexedSeq[T] { def apply(idx: Int): T = array(idx) def length: Int = array.length } 

(当然你仍然可以修改内容,如果你有权访问底层数组,但我会确保数组不会传递到我的程序的其他部分)。

Interesting Posts