2011-08-24 28 views
7

tôi thấy vấn đề này của scala: https://issues.scala-lang.org/browse/SI-4939vấn đề 'đối tượng Foo {val 1 = 2} `trong scala

Có vẻ chúng ta có thể xác định một phương pháp có tên là một con số:

scala> object Foo { val 1 = 2 } 
defined module Foo 

Nhưng chúng ta có thể 't gọi nó:

scala> Foo.1 
<console>:1: error: ';' expected but double literal found. 
     Foo.1 

Và chúng ta có thể gọi nó bên trong đối tượng:

scala> object O { val 1 = 1; def x = 1 } 
defined module O 
scala> O.x 
res1: Int = 1 

Và theo sẽ ném lỗi:

scala> object O { val 1 = 2; def x = 1 } 
defined module O 
scala> O.x 
scala.MatchError: 2 
    at O$.<init>(<console>:5) 
    at O$.<clinit>(<console>) 
    at .<init>(<console>:7) 
    at .<clinit>(<console>) 
    at RequestResult$.<init>(<console>:9) 

tôi sử dụng scalac -Xprint:typer để xem mã, phần val 1 = 2 là:

<synthetic> private[this] val x$1: Unit = (2: Int(2) @unchecked) match { 
    case 1 =>() 
} 

Từ đó, chúng ta có thể thấy tên phương pháp thay đổi để x$1, và chỉ có thể được gọi bên trong đối tượng đó.

Và việc giải quyết các vấn đề đó là: Sẽ không Fix

Tôi muốn biết là có lý do nào để cho phép một số là tên của một phương pháp? Có trường hợp nào chúng ta cần sử dụng phương thức "số" không?

+0

thảo luận thêm thông tin trong danh sách gửi thư liên kết từ vé: https://groups.google.com/ Diễn đàn/#! topic/scala-user/k57U6jt8Za0 –

Trả lời

10

Không có tên "1" bị ràng buộc tại đây. val 1 = 2 là biểu thức khớp mẫu, theo cùng một cách val (x,2) = (1,2) liên kết x đến 1 (và sẽ ném một số MatchError nếu phần tử thứ hai không giống nhau). Nó được cho phép bởi vì không có lý do thực sự để thêm một trường hợp đặc biệt để cấm nó; theo cách này, val hoạt động khớp mẫu (gần như) giống hệt như cách đối sánh mẫu match.

+1

Điều đó có ý nghĩa, nhưng thật lạ khi một 'val' với tên' x $ 1' đang được tạo. –

+0

Chi tiết triển khai. Trường hợp một val liên kết chính xác một tên là đặc biệt-cased, do đó bạn không nhận được một 'Tuple1' (thậm chí tồn tại?), Nhưng trường hợp nó liên kết không ai nhận được một (bán) giá trị vô danh để giữ kết quả. Hãy thử 'val hd :: tl = List (1,2)' và bạn sẽ thấy một 'x $ 1' tương tự được tạo để giữ một bộ tuple có quyền truy cập" hd "và" tl "accessors. Trong trường hợp '1 = 1'," chủ sở hữu "là" Tuple0 "tức là' Đơn vị'. –

+0

+1 đây có thể là hành vi được mong đợi cho các lập trình viên bằng các ngôn ngữ chức năng, ít hơn cho những người có nền OOP. Btw, Haskell hoạt động theo cách tương tự. 'test x = (x, 1) trong đó (x, 1) = (1, 2)' biên dịch, nhưng thất bại khi cố gắng gọi 'test 2' với ngoại lệ' Mẫu không thể chối bỏ được cho mẫu (x, 1) ' –

0

Như mọi khi, bạn có thể sử dụng dấu gạch chéo ngược để thoát khỏi tên. Tôi thấy không có vấn đề trong việc hỗ trợ các tên như vậy - hoặc bạn sử dụng chúng và chúng hoạt động cho bạn hoặc chúng không hoạt động cho bạn và bạn không sử dụng chúng.

+1

Backticks không hoạt động đối với tôi, đây có phải là ý của bạn không? 'đối tượng Foo {val 1 = 2}; Foo. \ '1 \' ' –

+0

Đúng, đó là ý của tôi. –

4

Thường có hai yếu tố trong loại quyết định:

  1. Có rất nhiều lỗi trong Scalac đó là ưu tiên cao hơn nhiều, và lỗi nguồn lực sửa chữa còn hạn chế. Hành vi này là lành tính và do đó ưu tiên thấp.

  2. Có chi phí dài hạn cho bất kỳ sự gia tăng nào về độ phức tạp của đặc tả ngôn ngữ và hành vi hiện tại phù hợp với thông số kỹ thuật. Một khi mọi thứ bắt đầu nhận được vỏ bọc đặc biệt, có thể có hiệu ứng tuyết lở.

Đó là sự kết hợp của cả hai.


Cập nhật.Dưới đây là những gì có vẻ xa lạ với tôi:

val pair = (1, 2) 
object Foo 
object Bar 

val (1, 2) = pair  // Pattern matching on constants 1 and 2 
val (Foo, Bar) = pair // Pattern matching on stable ids Foo and Bar 
val (foo, bar) = pair // Binds foo and bar because they are lowercase 
val 1 = 1    // Pattern matching on constant 1 
val Foo = 1   // *Not* pattern matching; binds Foo 

Nếu val 1 = 1 là mô hình phù hợp, thì tại sao nên val Foo = 1 bind Foo chứ không phải là mô hình phù hợp?

Cập nhật 2. Daniel Sobral chỉ ra rằng đây là một ngoại lệ đặc biệt, và Martin Odersky gần đây wrote the same.

+0

'val Foo = 1' cũng như' val \ 'foo \' = 1' là các ngoại lệ cho phép ràng buộc bình thường với các mã định danh này. –

+0

@Daniel Với tôi, có vẻ như nhất quán nhất là không thực hiện khớp mẫu nếu biểu thức là một số nhận dạng duy nhất. Tức là, mở rộng "ngoại lệ" thống nhất. –

+0

@KiptonBarros: 1 không phải là số nhận dạng và chúng tôi muốn 1 là mẫu khớp trong 'x match {case 1 => ...}'. Dường như để có tính đồng nhất theo quy tắc hiện hành, val 1 = x phải được hiểu là khớp mẫu. Tôi nghĩ rằng thay vào đó người ta có thể cấm các trận đấu mẫu liên kết _no biến_ trong câu lệnh 'val', và điều này cũng sẽ cấm 'val Seq() = expr', có thể được thay thế bằng' assert (expr == Seq()) ', như 'val 1 = expr' tương đương với' assert (expr == 1) '. [Tôi phớt lờ về mục đích thực tế là 'khẳng định có thể được elided, người ta có thể có một khẳng định không elidable nếu muốn]. – Blaisorblade

1

Dưới đây là một vài ví dụ để chứng tỏ LHS của một bài tập là nhiều hơn chỉ là một cái tên:

val pair = (1, 2) 
val (a1, b1) = pair // LHS of the = is a pattern 
val (1, b2) = pair // okay, b2 is bound the the value 2 
val (0, b3) = pair // MatchError, as 0 != 1 
val a4 = 1 // okay, a4 is bound to the value 1 
val 1 = 1 // okay, but useless, no names are bound 
val a @ 1 = 1 // well, we can bind a name to a pattern with @ 
val 1 = 0 // MatchError 
Các vấn đề liên quan