Pattern Matching

Hello Everyone,
I was reading kinds of pattern matches in Martin Odersky’s book wherein its mentioned that we can use lowercase letters as Constant Patterns which are otherwise used as Variable Patterns, so I simply typed this code in intellij and was expecting result as OK

object Test extends App {

import math.E

E match {
case pi => s"Strange math? Pi" + pi
case _ => “OK”
}
}
its throwing compilation error as:

Error not found: value pi
case pi => “Strange math? Pi” + pi.
Also please note that there are back ticks around pi in case pi inside match which are not visible in the editor here.

tosu

I think the problem is exactly those ticks around pi. By stating it that way, I believe you are making it into a constant pattern – which means that there needs to be a symbol named pi for it to match against, and you haven’t defined one. The error is exactly correct – there is currently no value named pi.

If you change the import to:

import math.{E, Pi => pi}

then this compiles correctly, because now you have a value named pi

@jducoeur has it right: the backticks are crucial. From the spec:

8.1.1 […] A variable pattern x is a simple identifier which starts with a lower case letter. It matches any value, and binds the variable name to that value. The type of x is the expected type of the pattern as given from outside. A special case is the wild-card pattern _ which is treated as if it was a fresh variable on each occurrence.

and

8.1.5 […] A stable identifier pattern is a stable identifier r. The type of r must conform to the expected type of the pattern. The pattern matches any value v such that r == v (see here).

To resolve the syntactic overlap with a variable pattern, a stable identifier pattern may not be a simple name starting with a lower-case letter. However, it is possible to enclose such a variable name in backquotes; then it is treated as a stable identifier pattern.

8.1.1 is IMO a bit of an abomination. AFAIK it’s the only place where capitalization is significant in scala, and it tends to catch people by surprise.

The ambiguity tends to work out the way you want it in the vast majority of cases, making you only aware of the problem when you hit it, and then you don’t know what you hit.

Then again, in the vast majority of cases it’s actually what you want.

I also don’t have a much better suggestion on how to handle the ambiguity less ad-hoc.

How about the following rule: you can only introduce a new variable in the pattern by giving it a type annotation, otherwise it is a constant.

For example:

x match {

** case a => ??? // constant**

** case B => ??? // constant**

** case c: AnyRef => ??? // new variable**

** case D: AnyRef => ??? // new variable**
}

Best, Oliver

What if you want to introduce a new variable but match only a certain type? That currently works. Your suggestion would be a breaking change.

I believe Dotty has made a change in this area, but I’m not completely familiar.

@jducoeur, thanks for explanation, its working.I could have used something like this:

val p = 3.141592653589793

Pi match {
case p => println(s"Strange math? Pi = $p")
case _ => println(“OK”)
}