เหตุใดการจับคู่รูปแบบใน Scala จึงไม่ทำงานกับตัวแปร


113

ใช้ฟังก์ชันต่อไปนี้:

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

รูปแบบนี้เข้ากันได้ดี:

scala> fMatch("a")
It was a

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

สิ่งที่ฉันอยากจะทำได้มีดังต่อไปนี้:

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

สิ่งนี้ทำให้เกิดข้อผิดพลาดต่อไปนี้:

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

ฉันเดาว่านี่เป็นเพราะมันคิดว่าเป้าหมายนั้นเป็นชื่อที่คุณต้องการกำหนดให้กับสิ่งที่ป้อนเข้า สองคำถาม:

  1. ทำไมพฤติกรรมนี้ ไม่สามารถกรณีเพียงแค่มองหาตัวแปรที่มีอยู่ในขอบเขตที่มีประเภทที่เหมาะสมและใช้สิ่งเหล่านั้นก่อนและหากไม่พบให้ถือว่าเป้าหมายเป็นชื่อเพื่อจับคู่รูปแบบ?

  2. มีวิธีแก้ปัญหานี้หรือไม่? วิธีใดในการจับคู่รูปแบบกับตัวแปร? ท้ายที่สุดแล้วเราสามารถใช้คำสั่ง big if ได้ แต่ตัวพิมพ์ใหญ่จะดูหรูหรา


ที่เกี่ยวข้อง: stackoverflow.com/questions/7083502/…
Dave L.

1
ฉันเชื่อว่าคำถามรหัสและคำตอบนี้ล้าสมัยเมื่อ Scala 2.12.x. คงจะดีไม่น้อยหากมีการกล่าวถึงเวอร์ชันที่ใช้เป็นส่วนหนึ่งของคำถาม
conny

คำตอบ:


217

สิ่งที่คุณกำลังมองหาเป็นตัวบ่งชี้ที่มีเสถียรภาพ ใน Scala สิ่งเหล่านี้ต้องขึ้นต้นด้วยตัวอักษรตัวพิมพ์ใหญ่หรือล้อมรอบด้วย backticks

ทั้งสองอย่างนี้จะเป็นวิธีแก้ปัญหาของคุณ:

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

เพื่อหลีกเลี่ยงการอ้างถึงตัวแปรที่มีอยู่แล้วในขอบเขตการปิดล้อมโดยไม่ได้ตั้งใจฉันคิดว่ามันสมเหตุสมผลแล้วที่พฤติกรรมเริ่มต้นสำหรับรูปแบบตัวพิมพ์เล็กจะเป็นตัวแปรและไม่ใช่ตัวระบุที่คงที่ เฉพาะเมื่อคุณเห็นสิ่งที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่หรือในเครื่องหมายขีดหลังคุณจำเป็นต้องระวังว่าสิ่งนั้นมาจากขอบเขตรอบข้าง


3
ฉันพนันได้เลยว่านี่มาจาก Erlang โดยที่ตัวแปรเริ่มต้นด้วยอักษรตัวใหญ่และสัญลักษณ์ด้วยตัวพิมพ์เล็ก
Emil Ivanov

11
สังเกตว่าtargetเป็นค่า ( val) ไม่ใช่ตัวแปร ( var) มันใช้ไม่ได้กับตัวแปร
Luigi Plinge

ตัวพิมพ์ใหญ่? เฉดสีของ FORTRAN อ่อนแอมาร์ตินอ่อนแอ
Malvolio

13
@Emil จริงๆแล้วตัวระบุตัวพิมพ์ใหญ่ใน Scala แสดงถึงค่าคงที่ ดังนั้นรูปแบบที่ตรงกับตัวระบุตัวพิมพ์ใหญ่จึงถูกนำมาใช้เพื่อหมายถึงการเปรียบเทียบกับค่าคงที่ มันช่วยอย่างจริงจังในเรื่องต่างๆเช่นNilซึ่งฉันพนันได้เลยว่าเป็นเหตุผลที่แท้จริง
Daniel C. Sobral

ดูเหมือนว่าหนึ่งไม่สามารถใช้เป็นรหัสคงที่จะมีการแข่งขันรูปแบบกับมันวิธีเดียวที่ดูเหมือนว่าจะใช้ยามเท่าเทียมกันเช่นthis case x if x == this =>น่าจะเป็นข้อ จำกัด ทางวากยสัมพันธ์มิฉะนั้นควรใช้ความหมายอย่างน้อยภายในobjects
Nader Ghanbari
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.