2012-03-15 27 views
8

Tôi muốn để có thể làm điều này:Scala - thêm unapply để int

scala> val Int(i) = "1" 
i: Int = 1 

Nhưng Int không có một phương pháp unapply.

Tôi đã tìm thấy this answer cung cấp hướng dẫn về cách thêm ngầm một phương thức vào đối tượng hiện có, vì vậy tôi đã dùng thử. Giải pháp mà họ đưa ra cho công trình, nhưng không may là không phù hợp với mẫu. Dưới đây là những gì tôi có:

object UnapplyInt { 
    val IntRE = """^(\d+)$""".r 
    def unapply(v: String): Option[Int] = v match { 
    case IntRE(s) => Some(s.toInt) 
    case _ => None 
    } 
} 
implicit def int2unapplyInt(objA: Int.type) = UnapplyInt 

Những trường hợp thử nghiệm đều tốt:

val UnapplyInt(i) = "1"  // pattern matching with unapply is fine 
val i = Int.unapply("1").get // implicit conversion is fine 

Nhưng người tôi muốn thất bại:

scala> val Int(i) = "1" 
<console>:10: error: object Int is not a case class constructor, nor does it have an unapply/unapplySeq method 
     val Int(i) = "1" 
     ^

Nếu các công trình chuyển đổi ngầm và mô hình phù hợp với unapply công trình, tại sao Scala không đặt hai thứ này lại với nhau để phù hợp với mô hình ngầm?

Trả lời

8

chỉnh sửa Vì vậy, lý do ban đầu của tôi không tốt. Lý do thực sự là từ Section 8.1.8 of the Scala language spec

Syntax: 
    SimplePattern ::= StableId ‘(’ [Patterns] ‘)’ 

Đó là, các đối tượng vắt phải được ổn định, và một chuyển đổi ngầm là không ổn định. Không có giải thích cho lý do tại sao vắt phải ổn định; Tôi nghi ngờ đó là vì Scala không muốn đối xử với vắt như là một biểu vì đó có thể nhanh chóng trở thành mơ hồ:

... match { 
    foo(bar)(baz) 
} 

Bây giờ đó là các nhà xây dựng và đó là những biến mô hình?

May mắn là bạn có thể làm điều này và nó hoạt động tốt (mặc dù, như bạn nhận xét, giới thiệu các vấn đề khác):

object Int { 
    def unapply(v: String) = try Some(v.toInt) 
     catch { case _: NumberFormatException => None } 
} 

val Int(i) = "5" 

kể từ khi loại Int và đối tượng Int là trong không gian tên khác nhau.

+0

Ha! Giải pháp được đề xuất của bạn là những gì tôi đang sử dụng hiện tại. Tôi không hoàn toàn hài lòng với nó bởi vì nó đòi hỏi phải có hai không gian tên khác nhau, có nghĩa là tôi không thể có 'Int.MaxValue' và' val Int (i) = "5" 'trong cùng một vị trí. – dhg

+0

@dhg Đúng. Và bây giờ tôi nghĩ nhiều hơn về nó, tôi nghĩ lý do trong câu trả lời của tôi không hoàn toàn đúng. Lý do thực sự là các biểu thức mẫu không thể giống như các biểu thức thông thường vì Scala phải xác định thứ gì là các nhà xây dựng và biến là gì ... – Owen

+1

Bạn mất tôi ở phần cuối cùng đó. – dhg

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