2015-05-08 13 views
8

Kiểm tra phiên REPL này (tôi đã dọn dẹp nó cho dễ đọc):Ngẫu nhiên cấp ở Scala là Odd

scala> val x = 1 to 10 
x: Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

scala> val y = x.toSeq 
y: Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

scala> x eq y 
res14: Boolean = true 

scala> util.Random.shuffle(y) 
<console>:10: error: Cannot construct a collection of type scala.collection.AbstractSeq[Int] with elements of type Int based on a collection of type scala.collection.AbstractSeq[Int]. 
       util.Random.shuffle(y) 
           ^

scala> util.Random.shuffle(x) 
res16: scala.collection.immutable.IndexedSeq[Int] = Vector(8, 3, 4, 2, 10, 9, 7, 5, 6, 1) 

Đầu tiên, điều này sẽ làm việc không phụ thuộc vào thực tế là các loại khác nhau. Câu hỏi đặt ra là 'Tại sao?'

Trả lời

2

Vì lý do nào đó, nhập suy luận cho số shuffle sẽ tạo ra một kết quả khác nhau cho số Inclusive trái ngược với Range.

Lý do toSeq kết quả trong Range là định nghĩa của nó ngây thơ thu hẹp loại:

override def toSeq = this 

Có một vấn đề mở để suy ra kiểu kết quả của phương pháp ghi đè để thay thế.

Hiển thị rằng REPL là không nói dối:

scala> import util.Random.shuffle 
import util.Random.shuffle 

scala> val x = 1 to 10 
x: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

scala> val y = x.toSeq 
y: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

scala> val z: Range = x 
z: Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

scala> shuffle(x) 
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 5, 2, 10, 9, 6, 3, 7, 4, 8) 

scala> shuffle(y) 
<console>:11: error: Cannot construct a collection of type scala.collection.AbstractSeq[Int] with elements of type Int based on a collection of type scala.collection.AbstractSeq[Int]. 
       shuffle(y) 
        ^

Snipping để xem những gì đã được suy ra và những gì tiềm ẩn đã được sử dụng:

scala> :replay -Xprint:typer 

Replaying: shuffle(x) 
     private[this] val res0: scala.collection.immutable.IndexedSeq[Int] = scala.util.Random.shuffle[Int, scala.collection.immutable.IndexedSeq]($line5.$read.$iw.$iw.x)(immutable.this.IndexedSeq.canBuildFrom[Int]); 

scala> shuffle(y) 
     private[this] val <res1: error>: <error> = scala.util.Random.shuffle[Int, scala.collection.AbstractSeq]($line6.$read.$iw.$iw.y)(); 

thay vì những gì bạn hy vọng:

scala> shuffle[Int, collection.immutable.IndexedSeq](z) 
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(6, 5, 3, 8, 4, 1, 2, 10, 7, 9) 

Với -Ytyper-debug, có thêm một tham số kiểu A có vẻ như để cho nó bắt đầu ed cho Inclusive, nhưng tôi không biết điều đó đến từ đâu.

| | | | |-- x BYVALmode-EXPRmode-POLYmode (site: value res3 in $iw) 
| | | | | \-> scala.collection.immutable.Range.Inclusive 
| | | | solving for (T: ?T, CC: ?CC) 
| | | | solving for (A: ?A) 
| | | | [adapt] [A]=> scala.collection.generic.CanBuildFrom[scala.collect... adapted to [A]=> scala.collection.generic.CanBuildFrom[scala.collect... based on pt scala.collection.generic.CanBuildFrom[scala.collection.immutable.IndexedSeq[Int],Int,scala.collection.immutable.IndexedSeq[Int]] 
| | | | |-- [T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit bf: ... EXPRmode (site: value res3 in $iw) 
| | | | | \-> scala.collection.immutable.IndexedSeq[Int] 
| | | | [adapt] [T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit bf: ... adapted to [T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit bf: ... 
| | | | \-> scala.collection.immutable.IndexedSeq[Int] 

Đó có phải là lỗi hoặc hành vi không?

Làm cho nó đơn giản:

scala> import language.higherKinds, collection.TraversableOnce, collection.generic.CanBuildFrom 
import language.higherKinds 
import collection.TraversableOnce 
import collection.generic.CanBuildFrom 

scala> def f[T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit cbf: CanBuildFrom[CC[T],T,CC[T]]): CC[T] = null.asInstanceOf[CC[T]] 
f: [T, CC[X] <: scala.collection.TraversableOnce[X]](xs: CC[T])(implicit cbf: scala.collection.generic.CanBuildFrom[CC[T],T,CC[T]])CC[T] 

scala> f(1 to 10) 
res0: scala.collection.immutable.IndexedSeq[Int] = null 

scala> f(1 until 10) 
<console>:12: error: Cannot construct a collection of type scala.collection.AbstractSeq[Int] with elements of type Int based on a collection of type scala.collection.AbstractSeq[Int]. 
       f(1 until 10) 
      ^
5

Đó là SI-6948, a bug do sự tan vỡ scala cơ bản.

Dưới đây là một số nice long commit message với một số giải thích bổ sung.

+0

https://gitter.im/scala/scala?at=554d5ab5675c1d50549ec0f1 được cho là mang tính thể hiện rõ ràng hơn về mặt typography. –