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

发布于 2024-10-28 00:04:21 字数 531 浏览 1 评论 0原文

我在Scala 2.8.1标准库的源代码中搜索了@specialized的使用。看起来只有少数特征和类使用此注释:Function0Function1Function2Tuple1Tuple2Product1Product2AbstractFunction0AbstractFunction1AbstractFunction2< /代码>。

没有一个集合类是@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 Ints, avoiding boxing and unboxing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终遇你 2024-11-04 00:04:21

专业化对班级规模的成本很高,因此必须慎重考虑。就收藏的具体情况而言,我想影响将会是巨大的。

尽管如此,这仍然是一项持续的努力——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.

ゞ记忆︶ㄣ 2024-11-04 00:04:21

专业化在类的大小和编译时间方面都可能是昂贵的(指数)。它不仅仅是像接受的答案所说的大小。

打开你的 scala REPL 并输入以下内容。

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 种不同的基本类型( void、boolean、byte、char、int、long、short、double、float)。因此,基本上您最终会得到 20 个类,而不是 2 个。

回到具有 5 个专用模板参数的特征,为可能的原始类型的每种组合生成类。即其复杂性呈指数级增长。

2 * 10 ^ (没有专用参数)

如果您正在为特定的原始类型定义一个类,则应该更明确地说明它,例如

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

可以理解,在构建通用目的时必须节俭使用专用图书馆。

这里是 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.

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

Sorry :-). Its like a compiler bomb.

Now, lets take a simple trait

trait Foo[Int]{ }

The above will result in two compiled classes. Foo, the pure interface and Foo$1, the class implementation.

Now,

trait Foo[@specialized A] { }

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

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

Understandably one has to be frugal using specialized when building general purpose libraries.

Here is Paul Phillips ranting about it.

离线来电— 2024-11-04 00:04:21

我自己的问题的部分答案:我可以将数组包装在 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
}

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

Partial answer to my own question: I can wrap an array in an IndexedSeq like this:

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
}

(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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文