为什么在Scala的标准库中@specialized的东西很少?

Jes*_*per 38 collections performance autoboxing scala specialized-annotation

我搜索了@specializedScala 2.8.1标准库的源代码中的用法.它看起来像只性状一把类使用此批注:Function0,Function1,Function2,Tuple1,Tuple2,Product1,Product2,AbstractFunction0,AbstractFunction1,AbstractFunction2.

没有集合类@specialized.为什么不?这会产生太多的课程吗?

这意味着使用具有基本类型的集合类是非常低效的,因为将会有大量不必要的装箱和拆箱.

拥有s 的不可变列表或序列(具有IndexedSeq特征)的最有效方法是什么Int,避免装箱和拆箱?

Dan*_*ral 18

专业化课程的成本很高,因此必须仔细考虑.在收藏品的特殊情况下,我认为影响将是巨大的.

尽管如此,这仍是一项持续的努力 - Scala图书馆几乎没有开始专业化.

  • 这是对的.来自Scala Days 2010 @Specialized的视频,Iulian Dragos解释了为什么它不是无处不在:http://days2010.scala-lang.org/node/138/151 (8认同)
  • @KevinMeredith嗯,一方面,直到Java 7,它[限制为64 KB](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms- 4.9.1).在编写Android时,它也会出现问题. (4认同)
  • 我还浏览了Scala 2.9 RC1库的源代码,不幸的是它似乎没有任何改变! (2认同)

sma*_*007 16

在类的大小和编译时,Specialized可能是昂贵的(指数).它的大小不仅仅是接受的答案.

打开你的scala REPL并输入.

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

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

现在,让我们采取一个简单的特点

trait Foo[Int]{ }
Run Code Online (Sandbox Code Playgroud)

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

现在,

trait Foo[@specialized A] { }
Run Code Online (Sandbox Code Playgroud)

这里的专用模板参数被扩展/重写为9种不同的基本类型(void,boolean,byte,char,int,long,short,double,float).所以,基本上你最终会得到20个而不是2个.

回到具有5个专用模板参数的特征,可以为每种可能的基元类型组合生成类.即它的复杂性指数.

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

如果要为特定的基本类型定义类,则应该更加明确它,例如

trait Foo[@specialized(Int) A, @specialized(Int,Double) B] { }
Run Code Online (Sandbox Code Playgroud)

可以理解的是,在构建通用库时使用专业人员必须节俭.

是Paul Phillips对此的咆哮.

  • 但是你并不总是需要专注于所有八种原始类型加上"void"; 你也可以专门研究`Int`,例如,使用`@specialized(Int)`. (3认同)

Jes*_*per 6

部分回答我自己的问题:我可以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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 因为你隐藏在IndexedSeq后面仍然没有说服编译器不使用自动装箱.例如,如果我在下面运行`:javap -c`:`object Test {val a = arrayToIndexedSeq(Array(1,2,3)); val i:Int = a(0)}` - 你会看到val i = a(0)_does_ boxing(在`SeqLike`中).... (3认同)
  • 我不知道.我想我们需要提出请求,为集合添加更多专业化.Martin Odersky在这里承诺:http://www.scala-lang.org/node/7285; 我想这个问题是由于新集合中特征的重要因素,如果你想要Vector专门化,你最终将不得不专门化十几个涉及的特征,这反过来会造成图书馆大小的高膨胀.尽管如此,我认为我们应该投票支持这一点,对于Vector来说它的性能很差,这实际上是scala的数字运算瑞士军刀. (2认同)