Pertanyaan Bagaimana Scala mengubah Int ke Double?


val d: Double = 42

Ketika saya mencoba menemukan konversi implisit melalui intellij, tidak ada hal menarik yang muncul. Juga, Int bukan subtipe dari Double. Jadi bagaimana Scala melakukannya?


5
2018-03-08 00:02


asal


Jawaban:


Singkat cerita: ini bukan konversi implisit biasa pada beberapa objek pendamping, jenis numerik mendapatkan perlakuan khusus.


Jika kita lari scala -print pada skrip ini:

val d: Double = 42

kami mendapatkan:

package <empty> {
  object Main extends Object {
    def main(args: Array[String]): Unit = {
      new <$anon: Object>();
      ()
    };
    def <init>(): Main.type = {
      Main.super.<init>();
      ()
    }
  };
  final class anon$1 extends Object {
    private[this] val d: Double = _;
    <stable> <accessor> private def d(): Double = anon$1.this.d;
    def <init>(): <$anon: Object> = {
      anon$1.super.<init>();
      anon$1.this.d = 42.0;
      ()
    }
  }
}

Dalam kode desugared, kita melihat literal ganda 42.0, tetapi tidak ada panggilan konversi apa pun fungsi (misalnya dari Predef). Jadi, konversi dari Int untuk Double tidak boleh terjadi saat runtime, tetapi pada tahap awal kompilasi.

Itu bagian 3.5.3 dari spesifikasi memberitahu kita itu Int  lemah sesuai untuk Double karena transitivitas hubungan kesesuaian lemah <:w:

Int <:w Long <:w Float <:w Double

Selanjutnya, Bagian 6.26.1 (Konversi Nilai) memberitahu kita bahwa aturan untuk pelebaran numerik berlaku jika sebuah ekspresi e tipe T muncul di posisi di mana ekspresi mengetik pt diharapkan dan T lemah sesuai pt. Dalam hal ini, kita dapat menerapkan aturan dengan

  • ekspresi e = 42
  • jenis ekspresi T = Int
  • jenis yang diharapkan pt = Double

Demikian, 42 dikonversi menjadi 42.0 menggunakan toDouble. Karena ini adalah konstanta yang dapat diproses pada waktu kompilasi, kami tidak melihat toDouble dalam kode yang tidak diinginkan. Namun, jika kita merusak program serupa dengan yang tidak konstan nilai

val d: Double = (new scala.util.Random).nextInt(42)

kami mendapatkan:

package <empty> {
  object Main extends Object {
    def main(args: Array[String]): Unit = {
      new <$anon: Object>();
      ()
    };
    def <init>(): Main.type = {
      Main.super.<init>();
      ()
    }
  };
  final class anon$1 extends Object {
    private[this] val d: Double = _;
    <stable> <accessor> private def d(): Double = anon$1.this.d;
    def <init>(): <$anon: Object> = {
      anon$1.super.<init>();
      anon$1.this.d = new scala.util.Random().nextInt(42).toDouble();
      ()
    }
  }
}

dan toDouble ada di sana, sebagaimana ditentukan.


11
2018-03-08 00:43