2013-06-24 29 views
5

Tôi đã nhìn vào định nghĩa của toArray cho hashmaps:Tại sao scaladoc nói HashMap.toArray trả về mảng [A] thay vì mảng [(A, B)]?

http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.HashMap

Nó có

toArray: Array[A] 
def toArray[B >: (A, B)](implicit arg0: ClassTag[B]): Array[B] 

Tôi hoàn toàn không hiểu được điều này - bit đầu tiên nói rằng bạn nhận được một Array [A] , nhưng phần thứ hai nói bạn lấy Array [B]? Cả trong số này là những gì tôi mong đợi - Array [(A, B)]

Khi tôi kiểm tra xem nó bản thân mình:

scala> val x = scala.collection.mutable.HashMap[String, Int]() 
x: scala.collection.mutable.HashMap[String,Int] = Map() 

scala> x.put("8", 7) 
res0: Option[Int] = None 

scala> x foreach println 
(8,7) 

scala> x.toArray 
res2: Array[(String, Int)] = Array((8,7)) 

tại sao không phải là nó như ToList?

toList: scala.List[(A, B)] 
+0

Tất cả các câu trả lời tuyệt vời, cảm ơn! – Austin

Trả lời

5

Scaladoc có tất cả các loại lỗi tinh tế. Vấn đề ở đây là bạn đang thấy phiên bản "đơn giản hóa" của chữ ký phương thức (có nghĩa là một cách để truyền tải phần quan trọng của chữ ký và ẩn những thứ như CanBuildFrom trong các phương thức map/flatMap, thực sự là chi tiết triển khai). Việc đơn giản hóa có chút ít ở đây và dường như không có ý nghĩa gì nhiều. Nếu bạn bấm vào "chữ ký đầy đủ" liên kết, bạn sẽ thấy rằng chữ ký thật trông giống như:

def toArray[B >: (A, B)](implicit arg0: ClassTag[B]): Array[B] 

Trong thực tế điều này vẫn còn sai, như chúng ta chắc chắn không thể có một loại B mà B>: (A, B). Nó nên được nhiều hơn như:

def toArray[C >: (A, B)](implicit arg0: ClassTag[C]): Array[C] 

Vấn đề là có thực sự hai B s: cái đầu tiên xuất phát từ việc kê khai HashMap lớp đó (HashMap[A, +B]) trong khi người kia xuất phát từ phương pháp toArray quy định tại cơ sở của mình lớp TraversableOnce (def toArray[B >: A](implicit arg0: ClassTag[B]): Array[B]). Nó chỉ xảy ra rằng máy phát điện vô hướng không thể loại trừ hai trường hợp của B

2

API mà bạn thấy trong các Scaladoc của toArray:

def toArray[B >: (A, B)](implicit arg0: ClassTag[B]): Array[B] 

Tương đương với:

def toArray[C >: (A, B)](implicit arg0: ClassTag[C]): Array[C] 

Sự lựa chọn của các loại biến B là thực sự đáng tiếc (và thậm chí có thể một lỗi Scaladoc, tôi không chắc chắn nếu bạn được phép viết điều đó). Về cơ bản, điều này có nghĩa là bạn sẽ nhận được một dãy siêu kiểu cụ thể nhất của (A,B)ClassTag có sẵn. Yêu cầu ClassTag để tạo Array. Điều này về cơ bản có nghĩa là nếu tại thời gian biên dịch, loại thời gian chạy của Map bạn đang chuyển đổi hoàn toàn được biết đến, bạn sẽ nhận được Array[(A,B)]. Tuy nhiên, nếu bạn đã dựng sẵn Map ở đâu đó, loại thời gian chạy của kết quả Array sẽ phụ thuộc vào loại được truyền lên, chứ không phụ thuộc vào loại thời gian chạy. hành vi khác với toList và do các hạn chế của JVM về cách tạo mảng gốc.

1

Scaladoc chỉ sai vì nó kế thừa toArray từ TraversableOnce, trong đó loại bộ sưu tập là A và giá trị trả lại là B. Điều Array[A] được để lại từ TraversableOnce trong đó A là bất cứ điều gì TraversableOnce đang chuyển ngang (trong trường hợp này, thực tế là (A,B) cho định nghĩa khác là AB); và mặc dù nó điền vào các (A,B) đúng cách ở dạng dài, nó vẫn sử dụng B làm biến trở lại mới thay vì một chữ cái khác như C.

Loại khó hiểu! Nó thực sự nên đọc

def toArray[C >: (A,B)](...[C]): Array[C] 

và các hình thức ngắn nên

toArray: Array[(A,B)] 

giống như bạn mong đợi.

Các vấn đề liên quan