Search code examples
scalareferential

Option literal vs. Option variable


can anyone explain the behaviour of this snippet:

def test = {
  val xt: Option[String] = Some("1")
  val xx: String = "2"
  xt match {
    case Some(xx) => println("match")
    case _ => println("no match")
  }
  xt match {
    case Some("2") => println("match")
    case _ => println("no match")
  }
}

The Result is

match
noMatch

Why is there a difference when I change the val against the string literal ?


Solution

  • The expression case Some(xx) doesn't match against the value of xx which is in scope, but rather matches anything and binds that result to a new variable called xx, shadowing the outer definition.

    If you want to match against the existing variable, either use backticks:

    def test = {
      val xt: Option[String] = Some("1")
      val xx: String = "2"
      xt match {
        case Some(`xx`) => println("match")
        case _ => println("no match")
      }
      xt match {
        case Some("2") => println("match")
        case _ => println("no match")
      }
    }
    

    or rename the variable to start with an uppercase letter:

    def test = {
      val xt: Option[String] = Some("1")
      val Xx: String = "2"
      xt match {
        case Some(Xx) => println("match")
        case _ => println("no match")
      }
      xt match {
        case Some("2") => println("match")
        case _ => println("no match")
      }
    }
    

    edit: This is referred to as Stable Identifier Pattern defined in §8.1.5 in the Scala language specification