Почему сопоставление с образцом в Scala не работает с переменными?

Возьмите следующую функцию:

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

Я предполагаю, что это потому, что он думает, что target - это имя, которое вы бы хотели присвоить какому-либо входу. Два вопроса:

  1. Почему это поведение? Не может ли дело просто найти существующие в области видимости переменные, которые имеют соответствующий тип, и использовать их в первую очередь, а если ни одна не найдена, то рассматривать target как имя для сопоставления с образцом?

  2. Есть ли обходной путь для этого? Любой способ сопоставить шаблон с переменными? В конечном итоге можно использовать большое выражение if, но регистр соответствия более элегантен.

2 ответа

Решение

То, что вы ищете, это стабильный идентификатор. В Scala они должны либо начинаться с заглавной буквы, либо быть заключены в черточки.

Оба из них будут решения вашей проблемы:

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

Чтобы избежать случайной ссылки на переменные, которые уже существовали во включающей области, я думаю, что имеет смысл, что поведение по умолчанию состоит в том, что строчные буквы являются переменными, а не стабильными идентификаторами. Только когда вы видите что-то, начинающееся с заглавных букв или с обратной галочки, вы должны знать, что это происходит из окружающей области.

Вы также можете назначить его временной переменной внутри корпуса, а затем сравнить ее, это также будет работать.

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


Другие вопросы по тегам