Mengapa pencocokan pola di Scala tidak berfungsi dengan variabel?

113

Ambil fungsi berikut:

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

Pola ini cocok dengan baik:

scala> fMatch("a")
It was a

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

Yang ingin saya lakukan adalah sebagai berikut:

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

Ini memberikan kesalahan berikut:

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

Saya kira ini karena menurutnya target sebenarnya adalah nama yang ingin Anda tetapkan untuk apa pun inputnya. Dua pertanyaan:

  1. Mengapa perilaku ini? Tidak dapat kasus hanya mencari variabel yang ada dalam lingkup yang memiliki jenis yang sesuai dan menggunakan yang pertama dan, jika tidak ada yang ditemukan, maka perlakukan target sebagai nama untuk pencocokan pola?

  2. Apakah ada solusi untuk ini? Adakah cara untuk mencocokkan pola dengan variabel? Pada akhirnya, seseorang dapat menggunakan pernyataan if yang besar, tetapi kotak korek api lebih elegan.

Henry Henrinson
sumber
1
Saya yakin pertanyaan, kode, dan jawaban ini sudah usang pada Scala 2.12.x. Alangkah baiknya jika versi yang berlaku disebutkan sebagai bagian dari pertanyaan.
conny

Jawaban:

217

Yang Anda cari adalah pengenal yang stabil . Di Scala, ini harus dimulai dengan huruf besar, atau diapit oleh backticks.

Keduanya akan menjadi solusi untuk masalah Anda:

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")
    }
}

Untuk menghindari secara tidak sengaja merujuk ke variabel yang sudah ada di lingkup yang melingkupinya, menurut saya masuk akal bahwa perilaku default untuk pola huruf kecil menjadi variabel dan bukan pengidentifikasi stabil. Hanya ketika Anda melihat sesuatu yang dimulai dengan huruf besar, atau di belakang, Anda perlu menyadari bahwa itu berasal dari lingkup sekitarnya.

Ben James
sumber
3
Saya yakin ini berasal dari Erlang, di mana variabel dimulai dengan huruf kapital dan simbol dengan huruf kecil.
Emil Ivanov
11
Perhatikan itu targetadalah nilai ( val), dan bukan variabel ( var). Itu tidak bekerja dengan variabel.
Luigi Plinge
Huruf besar? Nuansa FORTRAN. Lemah, Martin, lemah.
Malvolio
13
@Emil Sebenarnya, pengidentifikasi yang dikapitalisasi di Scala menunjukkan konstanta. Jadi pola yang cocok pada pengenal huruf besar diartikan membandingkan dengan konstanta. Ini sangat membantu dengan hal-hal seperti Nil, yang saya yakin adalah alasan sebenarnya.
Daniel C. Sobral
Sepertinya seseorang tidak dapat menggunakan thissebagai pengenal yang stabil untuk mencocokkan pola dengannya, hanya cara yang tampaknya menggunakan penjaga kesetaraan seperti itu case x if x == this =>. Mungkin batasan sintaksis, jika tidak maka semantik harus bekerja setidaknya dalam objects.
Nader Ghanbari