2012-03-02 31 views
7

Tôi mới đến Scala, và tôi đang gặp khó khăn để hiểu tại sao đôi khi tôi không nhận được một lỗi loại khi cung cấp các luận cứ sai lầm khi Set.containsScala Set.contains không cho loại dự kiến ​​không phù hợp lỗi

Dưới đây là ví dụ nhanh sử dụng REPL (2.9.1.final):

scala> val baz = Map("one" -> 1, "two" -> 2) 
baz: scala.collection.immutable.Map[java.lang.String,Int] = Map(one -> 1, two -> 2) 

scala> baz.values.toSet.contains("asdf") 
res3: Boolean = false 

Tại sao tôi không nhận được loại không phù hợp ở đó?

Nếu tôi gán baz.values.toSet-val khác, và gọi contains trên đó, tôi làm được kiểm tra kiểu:

scala> val bling = baz.values.toSet 
bling: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> bling.contains("asdf") 
<console>:10: error: type mismatch; 
found : java.lang.String("asdf") 
required: Int 
       bling.contains("asdf") 
          ^

sai lầm ngu ngốc, tinh tế ngôn ngữ, hoặc biên dịch lỗi?

+0

Câu trả lời ngắn: ngôn ngữ tinh tế (subtyping và suy luận kiểu) –

Trả lời

12

OK, vì vậy Set là bất biến trong tham số kiểu của nó và nó hoạt động chính xác như nó nên

scala> Set(1, 2, 3) contains "Hi" 
<console>:8: error: type mismatch; 
found : java.lang.String("Hi") 
required: Int 
       Set(1, 2, 3) contains "Hi" 
            ^

Nhưng, như bạn nói:

scala> Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet contains "Hi" 
res1: Boolean = false 

Kết luận duy nhất chúng ta một cách hợp lý có thể đến là rằng loại số Set được đề cập là không phảiSet[Int]. Điều gì xảy ra nếu chúng tôi nói rõ ràng về scala, chúng tôi muốn có một số Set[Int]? Cùng một mảnh mã với một tham số kiểu tường minh chỉ hoạt động tốt (tức là nó không biên dịch):

scala> Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet[Int] contains "Hi" 
<console>:8: error: type mismatch; 
found : java.lang.String("Hi") 
required: Int 
       Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet[Int] contains "Hi" 
                     ^

Vấn đề là suy ra kiểu tham số được truyền cho phương thức toSet. Scala rõ ràng lấy contains "Hi" vào tài khoản và suy luận ra lub của IntString (tức Any)

+0

Bạn có nói rằng Scala được suy luận từ *** sử dụng tiếp theo * ** của tập hợp rằng tham số kiểu của tập dữ liệu phải rộng hơn, như 'Bất kỳ'? –

+0

Chết tiệt, đánh tôi với nó. 1 cho bạn. Một số giải thích thêm là khi bạn gọi 'baz.values.toSet.contains (" asdf ")', nó tìm ra kiểu gần nhất thỏa mãn điều kiện '[X>: Int]', và nó tìm thấy 'X' là' Bất kỳ ', có nghĩa là kết quả của' toSet' là 'Set [Any]'. Bởi vì điều này, bạn nên nói rõ ràng loại bạn muốn thiết lập được, như oxbow đã đề cập. – Dylan

+0

Bạn không nên giải thích rằng nó đang suy ra loại 'Đặt' là' Bất kỳ'? –

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