2012-09-09 46 views
5

Ai đó có thể giải thích tại sao mã sau đây biên dịch?Kết hợp mẫu Scala và suy luận kiểu

Option("foo") match { 
    case x: List[String] => println("A") 
    case _ => println("B") 
} 

Điều này cho tôi một cảnh báo (dự kiến) về xóa, nhưng vẫn biên dịch. Tôi mong đợi điều này sẽ xảy ra lỗi loại, giống như khi tôi đối sánh trên "foo" thay vì Option("foo").

Cảm ơn!

+1

Trông giống như một lỗi. Tôi sẽ báo cáo. – sschaef

Trả lời

2

Tôi giả định rằng trình biên dịch xử lý cả hai số OptionListProduct, đó là lý do tại sao nó biên dịch. Như bạn nói, cảnh báo về loại xóa được mong đợi. Dưới đây là một ví dụ sử dụng một sản phẩm:

scala> Option("foo") match { 
| case x: Tuple2[String,String] => println("TUPLE") 
| case x: List[String] => println("LIST") 
| case _ => println("OTHER") 
| } 
<console>:9: warning: non variable type-argument String in type pattern (String, String)  is unchecked since it is eliminated by erasure 
      case x: Tuple2[String,String] => println("TUPLE") 
       ^
<console>:10: warning: non variable type-argument String in type pattern List[String] is unchecked since it is eliminated by erasure 
      case x: List[String] => println("LIST") 
       ^

CẬP NHẬT w/r/t lớp trường hợp (vì bình luận dưới đây):

scala> case class Foo(bar: Int) 
defined class Foo 

scala> val y: Product = Foo(123) 
y: Product = Foo(123) 
+0

Dường như nó không liên quan gì đến 'Sản phẩm'. Tôi thay thế 'Tùy chọn (" foo ")' với lớp trường hợp của riêng tôi lấy tham số duy nhất và không có lỗi. – ghik

+2

Errr, các trường hợp tự động mở rộng Sản phẩm. Xem chỉnh sửa phản hồi. – timothy

+1

Ok, nhưng nó thực sự không phải là trường hợp lớp. Lớp không phải cuối cùng thông thường cũng không gây ra lỗi. – ghik

0

tôi nhận thấy rằng một lỗi được hiển thị khi lớp của giá trị mà bạn đối sánh được khai báo là cuối cùng (và chúng tôi biết rằng String là cuối cùng). Tôi vẫn không biết tại sao không có lỗi mà không có nó.

4

Mã này được nhận xét, vì vậy chúng ta hãy dành vài phút để thưởng thức rằng:

/** If we can absolutely rule out a match we can fail early. 
    * This is the case if the scrutinee has no unresolved type arguments 
    * and is a "final type", meaning final + invariant in all type parameters. 
    */ 

ý rằng Không là không chính thức, ví dụ. Tôi biết, phải không?

Nếu bạn đã bao giờ thử scalac -Ypatmat-debug, nhận xét đây có thể giúp:

https://github.com/scala/scala/pull/650

reachability là gần như trong tầm tay:

https://issues.scala-lang.org/browse/SI-6146

Nhưng tôi không thấy bất kỳ lời hứa nào về những gì có thể một ngày nào đó sẽ được cảnh báo. Vì lý do hiệu suất? Người ta cũng có thể nói, tại sao nó nên cảnh báo về một instanceOf [Foo [_]]?

Hiện tại, các phần thông số 8.2 - 8.4 khuyến khích lý do tại sao khớp với Foo [a] là thú vị (vì các giới hạn mua lại). Tôi nghĩ tôi sẽ đọc lại lần nữa. Sau một ít cà phê.

trait Foo[+A] 
final class Fuzz[+A] extends Foo[A] 
final object Fooz extends Foo[Nothing] 
object Futz extends Foo[Nothing] 

//error 
Fooz match { 
    case x: List[_] => println("A") 
    case _ => println("B") 
} 
//no error 
Futz match { ... } 
+0

Đẹp, hình dung nó sẽ là một số quirk với mô hình matcher nhưng không thể nhìn thấy nó cuối đêm qua :-) – timothy

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