Tại sao đối sánh mẫu trong Scala không hoạt động với các biến?


113

Thực hiện chức năng sau:

def fMatch(s: String) = {
    s match {
        case "a" => println("It was a")
        case _ => println("It was something else")
    }
}

Mẫu này phù hợp một cách độc đáo:

scala> fMatch("a")
It was a

scala> fMatch("b")
It was something else

Những gì tôi muốn có thể làm như sau:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case target => println("It was" + target)
        case _ => println("It was something else")
        }
}

Điều này gây ra lỗi sau:

fMatch: (s: String)Unit
<console>:12: error: unreachable code
               case _ => println("It was something else")

Tôi đoán điều này là do nó nghĩ rằng đích thực sự là một cái tên mà bạn muốn gán cho bất cứ thứ gì đầu vào. Hai câu hỏi:

  1. Tại sao hành vi này? Trường hợp không thể chỉ tìm kiếm các biến hiện có trong phạm vi có kiểu thích hợp và sử dụng những biến đó trước tiên và nếu không tìm thấy, sau đó coi đích như một cái tên để so khớp?

  2. Có một cách giải quyết cho điều này? Có cách nào để khớp mẫu với các biến không? Cuối cùng người ta có thể sử dụng một câu lệnh if lớn, nhưng trường hợp khớp thì thanh lịch hơn.



1
Tôi tin rằng câu hỏi, mã và câu trả lời này đã lỗi thời kể từ Scala 2.12.x. Sẽ rất tốt nếu phiên bản được áp dụng được đề cập như một phần của câu hỏi.
conny

Câu trả lời:


217

Những gì bạn đang tìm kiếm là một số nhận dạng ổn định . Trong Scala, chúng phải bắt đầu bằng chữ hoa hoặc được bao quanh bởi dấu gạch ngược.

Cả hai điều này sẽ là giải pháp cho vấn đề của bạn:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case `target` => println("It was" + target)
        case _ => println("It was something else")
    }
}

def mMatch2(s: String) = {
    val Target: String = "a"
    s match {
        case Target => println("It was" + Target)
        case _ => println("It was something else")
    }
}

Để tránh vô tình tham chiếu đến các biến đã tồn tại trong phạm vi bao quanh, tôi nghĩ rằng hành vi mặc định là đối với các mẫu chữ thường là biến chứ không phải là định danh ổn định. Chỉ khi bạn nhìn thấy thứ gì đó bắt đầu bằng chữ hoa hoặc dấu tích phía sau, bạn mới cần biết rằng nó đến từ phạm vi xung quanh.


3
Tôi cá rằng điều này đến từ Erlang, nơi các biến bắt đầu bằng một chữ cái viết hoa và các ký hiệu bằng chữ thường.
Emil Ivanov

11
Lưu ý rằng đó targetlà một giá trị ( val), và không phải là một biến ( var). Nó không hoạt động với các biến.
Luigi Plinge

Chữ hoa? Sắc thái của FORTRAN. Yếu ớt, Martin, yếu ớt.
Malvolio

13
@Emil Trên thực tế, các định danh viết hoa trong Scala biểu thị các hằng số. Vì vậy, một đối sánh mẫu trên mã định danh viết hoa được coi là so sánh với một hằng số. Nó thực sự hữu ích với những thứ như Nil, mà tôi cá là lý do thực sự.
Daniel C. Sobral

Có vẻ như người ta không thể sử dụng thisnhư một định danh ổn định để so khớp mẫu với nó, chỉ có cách là sử dụng một người bảo vệ bình đẳng như case x if x == this =>. Có thể là một hạn chế về mặt cú pháp, nếu không thì nó sẽ hoạt động về mặt ngữ nghĩa ít nhất là trong vòng objects.
Nader Ghanbari,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.