В сопоставлении с шаблоном scala, что такое подозрительное затенение с помощью шаблона переменной?
Когда я ввожу следующий код в Intellij, он выделяет x внутри матча с предупреждением "Подозрительное затенение с помощью шаблона переменной"
val x = "some value"
"test" match {
case x =>
}
Это говорит о том, что я меняю его на:
val x = "some value"
"test" match {
case `x` => //note backticks
}
Что такое подозрительное затенение и что делают backticks?!
Ответы
Ответ 1
case x
создает переменную с именем x
, которая соответствовала бы всем, и поскольку уже существует переменная с тем же именем, вы затеняете ее, используя одно и то же имя.
case `x`
использует значение переменной x
, которое было объявлено ранее, и будет соответствовать только входам с одинаковыми значениями.
PS
Вы можете оставить обратные тики, если имя переменной заглавны, как в
case Pi
Ответ 2
Выдержка из программирования в Scala [1]:
Литеральный идентификатор - это произвольная строка, заключенная в обратные тики (`...`)
. Некоторые примеры буквенных идентификаторов:
`x` `<clinit>` `yield`
Идея состоит в том, что вы можете поместить любую строку, принятую во время выполнения, в качестве идентификатора между обратными тиками. Результатом всегда является идентификатор Scala. Это работает, даже если имя, содержащееся в обратных тиках, будет Scala зарезервированным словом. Типичным примером использования является доступ к статическому методу yield
в классе Java Thread
. Вы не можете написать Thread.yield()
, потому что yield
является зарезервированным словом в Scala. Однако вы все равно можете называть метод обратными тиками, например Thread.`yield`()
.
Короче говоря, с `x`
вы сопоставляетесь со значением x
. С помощью x
вы создаете новую переменную, которая будет соответствовать чему-либо, и сохраните результат до x
.
[1] M. Odersky, L. Spoon, B. Venners, Programming in Scala, 2nd ed, Walnut Creek: Artima Press 2010, pp. 109 http://www.artima.com/pins1ed/functional-objects.html#i1517246665-1
Ответ 3
Случай внутри матча генерирует новый символ x
для получения согласованного значения. Это связано с тем, что, согласно соглашениям, ожидается, что идентификаторы нижних регистров будут ссылаться на значения и идентификаторы верхнего регистра на типы.
Таким образом, оператор case генерирует новый символ с тем же именем x
в качестве вашего начального значения, "затеняя" это исходное значение. "Затенение" IntelliJ означает, что он скрывает любые другие значения с тем же именем и, следовательно, делает их недоступными.
Он помещает это как подозрительное, потому что это затенение часто бывает непреднамеренным, что, по-видимому, имеет место в вашем примере.
Что касается обратных выходов, см., например, здесь: Требуется уточнение для Scala литеральных идентификаторов (обратных ссылок)
Тем не менее, они не кажутся хорошим решением. Лучше выбрать другое имя.