43

@specializedScala 2.8.1 の標準ライブラリのソース コードでの使用を検索しました。この注釈を使用するトレイトとクラスはほんの一握りのようです: Function0, Function1, Function2, Tuple1, Tuple2, Product1, Product2, .AbstractFunction0AbstractFunction1AbstractFunction2

コレクション クラスはどれも@specialized. なぜだめですか?これにより生成されるクラスが多すぎますか?

つまり、プリミティブ型でコレクション クラスを使用すると、不要なボックス化とボックス化解除が大量に発生するため、非常に非効率的です。

ボックス化とボックス化解除を回避して、s の不変リストまたはシーケンス (IndexedSeq特性を含む) を持つ最も効率的な方法は何ですか?Int

4

3 に答える 3

18

専門化はクラスのサイズに大きく影響するため、慎重に検討して追加する必要があります。コレクションの特定のケースでは、その影響は非常に大きいと思います。

それでも、これは進行中の取り組みです。Scala ライブラリの特化はまだ始まったばかりです。

于 2011-03-29T21:39:05.393 に答える
17

Specialized は、クラスのサイズとコンパイル時間の両方で高価 (指数関数的) になる可能性があります。受け入れられた回答が言うようなサイズだけではありません。

scala REPL を開き、これを入力します。

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

ごめん :-)。コンパイラ爆弾のようなものです。

では、簡単な特性を見てみましょう

trait Foo[Int]{ }

上記により、2 つのコンパイル済みクラスが生成されます。純粋なインターフェイスである Foo と、クラスの実装である Foo$1 です。

今、

trait Foo[@specialized A] { }

ここでの特殊なテンプレート パラメータは、9 つ​​の異なるプリミティブ型 (void、boolean、byte、char、int、long、short、double、float) に対して拡張/書き換えられます。したがって、基本的には 2 クラスではなく 20 クラスになります。

5 つの特殊なテンプレート パラメーターを持つトレイトに戻ると、可能なプリミティブ型のすべての組み合わせに対してクラスが生成されます。つまり、複雑さは指数関数的です。

2 * 10 ^ (特殊なパラメーターなし)

特定のプリミティブ型のクラスを定義している場合は、次のようにそれについてより明示する必要があります。

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

当然のことながら、汎用ライブラリを構築するときは、専用を使用して倹約する必要があります。

これは、ポール・フィリップスがそれについて怒鳴っています

于 2013-03-08T17:57:33.387 に答える
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
}

(もちろん、基になる配列にアクセスできる場合はコンテンツを変更できますが、配列がプログラムの他の部分に渡されないようにします)。

于 2011-03-29T19:19:17.430 に答える