为什么 Scala 标准库中 @specialized 的东西这么少?
我在Scala 2.8.1标准库的源代码中搜索了@specialized
的使用。看起来只有少数特征和类使用此注释:Function0
、Function1
、Function2
、Tuple1
、 Tuple2
、Product1
、Product2
、AbstractFunction0
、AbstractFunction1
、AbstractFunction2< /代码>。
没有一个集合类是@specialized
。为什么不呢?这会产生太多的类吗?
这意味着使用具有原始类型的集合类是非常低效的,因为会发生很多不必要的装箱和拆箱。
拥有 Int
的不可变列表或序列(具有 IndexedSeq
特征),避免装箱和拆箱的最有效方法是什么?
I've searched for the use of @specialized
in the source code of the standard library of Scala 2.8.1. It looks like only a handful of traits and classes use this annotation: Function0
, Function1
, Function2
, Tuple1
, Tuple2
, Product1
, Product2
, AbstractFunction0
, AbstractFunction1
, AbstractFunction2
.
None of the collection classes are @specialized
. Why not? Would this generate too many classes?
This means that using collection classes with primitive types is very inefficient, because there will be a lot of unnecessary boxing and unboxing going on.
What's the most efficient way to have an immutable list or sequence (with IndexedSeq
characteristics) of Int
s, avoiding boxing and unboxing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
专业化对班级规模的成本很高,因此必须慎重考虑。就收藏的具体情况而言,我想影响将会是巨大的。
尽管如此,这仍然是一项持续的努力——Scala 库才刚刚开始专业化。
Specialization has a high cost on the size of classes, so it must be added with careful consideration. In the particular case of collections, I imagine the impact will be huge.
Still, it is an on-going effort -- Scala library has barely started to be specialized.
专业化在类的大小和编译时间方面都可能是昂贵的(指数)。它不仅仅是像接受的答案所说的大小。
打开你的 scala REPL 并输入以下内容。
对不起 :-)。它就像一个编译器炸弹。
现在,让我们采用一个简单的特征
上面将产生两个编译的类。 Foo,纯接口和 Foo$1,类实现。
现在,
这里的专用模板参数被扩展/重写为 9 种不同的基本类型( void、boolean、byte、char、int、long、short、double、float)。因此,基本上您最终会得到 20 个类,而不是 2 个。
回到具有 5 个专用模板参数的特征,为可能的原始类型的每种组合生成类。即其复杂性呈指数级增长。
2 * 10 ^ (没有专用参数)
如果您正在为特定的原始类型定义一个类,则应该更明确地说明它,例如
可以理解,在构建通用目的时必须节俭使用专用图书馆。
这里是 Paul Phillips 对此的咆哮。
Specialized can be expensive ( exponential ) in both size of classes and compile time. Its not just the size like the accepted answer says.
Open your scala REPL and type this.
Sorry :-). Its like a compiler bomb.
Now, lets take a simple trait
The above will result in two compiled classes. Foo, the pure interface and Foo$1, the class implementation.
Now,
A specialized template parameter here gets expanded/rewritten for 9 different primitive types ( void, boolean, byte, char, int, long, short, double, float ). So, basically you end up with 20 classes instead of 2.
Going back to the trait with 5 specialized template parameters, the classes get generated for every combination of possible primitive types. i.e its exponential in complexity.
2 * 10 ^ (no of specialized parameters)
If you are defining a class for a specific primitive type, you should be more explicit about it such as
Understandably one has to be frugal using specialized when building general purpose libraries.
Here is Paul Phillips ranting about it.
我自己的问题的部分答案:我可以将数组包装在
IndexedSeq
中,如下所示:(当然,如果您有权访问底层数组,您仍然可以修改内容,但我会确保该数组没有传递到我的程序的其他部分)。
Partial answer to my own question: I can wrap an array in an
IndexedSeq
like this:(Ofcourse you could still modify the contents if you have access to the underlying array, but I would make sure that the array isn't passed to other parts of my program).