2016-11-20 12 views
2

私はスカラーのvalue classがコンパイラ時のオペレーションをインライン化していることを知っています。多分これスカラ値クラス、使用例

case class A(i: Int) extends AnyVal { 
    def +(that: A) = A(this.i + that.i) 
} 
A(1) + A(2) // After compile it equals to 1 + 2 

よう

しかし、それは私には大したことではないようです。

それはと思われていません

this.i + that.iを呼び出して、パフォーマンスを向上させるかもしれないが、なぜScalaの中value classと任意のユースケースを必要とするはるかに遅い

i + iよりも?

+0

* this.iを呼び出します+ that.iはi + iよりずっと遅くはないようです*どうやってこれを決めましたか?あなたはそのコードをマイクロベンチマークしましたか? –

+0

コールは高速です(これはJITコンパイラによってインライン展開される可能性が高い)ことに加えて、値クラスによってオブジェクトのインスタンス化が回避され、ガベージコレクションの負荷が軽減されます。 – Suma

答えて

5

なぜ、追加のクラスに単一の値をラップしますか?

1つの大きなユースケースがタイプセーフです。あなたがそうのように、お金を掛けることができます機能を持っているとしましょう:

def multiply(factor: Int, amount: Int): Int = ??? 

これに伴う問題は、二つの引数を混同し、したがって、間違って関数を呼び出すことは非常に容易になることです。値クラスを使用すると、Moneyタイプを作成することができますので、のような機能を再書き込み:あなたは間違った順序で引数を渡すしようとした場合

case class Money(amount: Int) extends AnyVal 
def multiply(factor: Int, amount: Money): Money = ??? 

今すぐあなたの特別な Moneyタイプで、コンパイラはあなたを教えてくれます。

値クラスではない場合、追加された型の安全性は、場合によってはパフォーマンス上のペナルティに値するものではないという人もいます。しかし、値クラスでは、実行時オーバーヘッドはありません(ただし、制限はあります:http://docs.scala-lang.org/overviews/core/value-classes.html)。

同じ目標を達成するための代替されている(無実行時のオーバーヘッド)箱なしscalazでタイプをタグ付け:http://eed3si9n.com/learning-scalaz/Tagged+type.html

例えばHaskellは同じ考えのためnewtypeを使用しています。なお:https://wiki.haskell.org/Newtype

+0

ご協力ありがとうございます。 –

1

値クラスは、実行時オブジェクトの割り当てを避けるためのScalaの仕組みです。これは、新しいAnyValサブクラスの定義によって達成されます。値クラスについて

詳しいのは、Scalaは値クラス(-printオプション)でどのように機能するかを見てみましょうここでValue Classes

6

です。あなたはScalaはクラスAで作業を避け、単にIntを返すIntIntが追加されます見ることができるように

final def +$extension($this: Int, that: Int): Int = $this.+(that) 
... 
A.+$extension(1, 2) 

case class A(i: Int) extends AnyVal { 
    def +(that: A) = A(this.i + that.i) 
} 
A(1) + A(2) 

がに変換されます。同時に:だからあなたはクラスAを3回インスタンス化する必要がある1 + 2計算する

def +(that: A): A = new A(this.i().+(that.i())) 
... 
new A(1).+(new A(2)) 

case class A(i: Int) { 
    def +(that: A) = A(this.i + that.i) 
} 
A(1) + A(2) 

がに変換されます。

+0

どのような素晴らしい説明!あなたの詳細をありがとう。値クラスを使用しない場合のパフォーマンスコストは明らかです –

関連する問題