4

編集: Scala 2.9.2 を使用しています

Scala では、Double をラップするカスタム クラスを定義しました。

class DoubleWrap( d : Double ) {
    def double( ) = d * 2
}

Double から DoubleWrap への暗黙的な変換:

implicit def wrapDouble( d : Double ) = new DoubleWrap( d )

これにより、次のことが可能になります。

scala> 2.5.double
res0: Double = 5.0

ただし、Scala には Int から Double への暗黙的な変換があるため、次のこともできます。

scala> 2.double
res1: Double = 4.0

この演算子は、double 型コレクションのすべての要素に適用することもできます。map

scala> List( 1.0, 2.0, 3.0 ).map( _.double )
res2: List[Double] = List(2.0, 4.0, 6.0)

ただし、関数を整数コレクションのすべての要素に適用しようとすると、機能しません。

scala> List( 1, 2, 3 ).map( _.double )
<console>:10: error: value double is not a member of Int
          List( 1, 2, 3 ).map( _.double )

なぜこれが事実なのか誰にも分かりますか?

4

2 に答える 2

3

scala では、暗黙の変換は自動的に連鎖されません。言い換えれば、コンパイラは、コードが意味をなす単一の暗黙的な変換を探し、2 つ (またはそれ以上) 連続する暗黙的な変換を適用しようとはしません。

あなたの例では、あなたができるという事実は、からin2.doubleへの暗黙的な変換があるという事実とは何の関係もありません。証明として、これを REPL で試してください:DoubleIntPredef

scala> val i: Int = 2
i: Int = 2

scala> i.double
<console>:13: error: value double is not a member of Int
              i.double

コンパイルされません。では、なぜ2.doubleコンパイルするのでしょうか。良い質問。私はこれを直感的に理解していると思っていました:そもそも値 2 または値 2.0 として2解釈できるので、私の直感は、このコンテキストでは何らかの形ですでに aであるということでした。ただし、これは間違っていると思います。驚くべきことに、次のものでもコンパイルされるからです: (またはさらに奇妙な: )。正直なところ、私はびっくりして、なぜこれがコンパイルされるのにコンパイルされないのかわかりません。IntDouble2Double(2:Int).double((1+1):Int).doubleval i: Int = 2; i.double

要約すると、scala が 2 つの暗黙的な変換を同時に適用しようとしないのは正常ですが、何らかの理由でこの規則は定数式には適用されないようです。

問題を解決する方法として、暗黙的な変換を変更して、それ自体が暗黙的に に変換可能な任意の型を受け入れるようにしDoubleます。実際には、これにより暗黙的な変換を連鎖させることができます。

implicit def wrapDouble[T <% Double]( d : T ) = new DoubleWrap( d )
于 2013-02-28T13:28:55.170 に答える
0

これはすぐに修正されるバグです。

于 2013-03-08T05:59:52.143 に答える