In scala pattern matching, what is suspicious shad

2020-02-08 23:48发布

问题:

When I type the following code into Intellij, it highlights the x inside the match with the warning "Suspicious shadowing by a Variable Pattern"

val x = "some value"
"test" match {
  case x =>
}

It suggests that I change it to:

val x = "some value"
"test" match {
  case `x` => //note backticks
}

What is suspicious shadowing and what do the backticks do?!

回答1:

case x

creates a variable named x, which would match everything and since a variable with the same name already exists you shadow it by using the same name.

case `x`

uses the value of the variable x which was declared before and would only match inputs with same values.

PS

You can leave the back ticks out if the name of the variable is capitalized as in

case Pi

Watch Pattern Matching Unleashed for more.



回答2:

An Excerpt from Programming in Scala [1]:

A literal identifier is an arbitrary string enclosed in back ticks (`...`). Some examples of literal identifiers are:

    `x` `<clinit>` `yield`

The idea is that you can put any string that's accepted by the runtime as an identifier between back ticks. The result is always a Scala identifier. This works even if the name contained in the back ticks would be a Scala reserved word. A typical use case is accessing the static yield method in Java's Thread class. You cannot write Thread.yield() because yield is a reserved word in Scala. However, you can still name the method in back ticks, e.g., Thread.`yield`().

In short, with `x` you are matching against the value of x. With x you are creating a new variable that will match anything and save the result to 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:

The case inside the match generates a new symbol x to receive the matched value. This is because, by convention, lower case identifiers are expected to refer to values and upper case identifiers to types.

So the case statement generates a new symbol of the same name x as your initial value, "shadowing" that original value. By "shadowing" IntelliJ means that it hides any other values of the same name and thus makes them inaccessible.

It flags this as suspicious because this shadowing is often inadvertent, as seems to indeed be the case in your example.

Regarding the backticks, see e.g. here: Need clarification on Scala literal identifiers (backticks) They don't really seem like a good solution, though. Better to pick a different name.