scala – pattern variable – start with lower case – all others constants

Variable or constant? Constant patterns can have symbolic names. You saw this already when we used Nil as a pattern. Here is a related example, where a pattern match involves the constants E (2.71828…) and Pi (3.14159…):
scala> import math.{E, Pi} import math.{E, Pi} scala> E match { case Pi => “strange math? Pi = “+ Pi case _ => “OK” }

res11: java.lang.String = OK
As expected, E does not match Pi, so the “strange math” case is not used. How does the Scala compiler know that Pi is a constant imported from scala.math,andnotavariablethatstandsfortheselectorvalueitself? Scala uses a simple lexical rule for disambiguation: a simple name starting with a lowercase letter is taken to be a pattern variable; all other references are taken to be constants.

 

 

scala – variable pattern

Variablepatterns A variable pattern matches any object, just like a wildcard. Unlike a wildcard, Scala binds the variable to whatever the object is. You can then use this variable to act on the object further. For example, Listing 15.6 shows a pattern match that has a special case for zero, and a default case for all other values. The default case uses a variable pattern so that it has a name for the value, no matter what it is.

 

expr match { case 0 => “zero” case somethingElse => “not zero: “+ somethingElse }

scala – constant pattern

Constantpatterns Aconstantpatternmatchesonlyitself. Anyliteralmaybeusedasaconstant. For example, 5, true, and “hello” are all constant patterns. Also, any val or singleton object can be used as a constant. For example, Nil, a singleton object,isapatternthatmatchesonlytheemptylist.

 

def describe(x: Any) = x match { case 5 => “five” case true => “truth” case “hello” => “hi!” case Nil => “the empty list” case _ => “something else” }

scala – constructor pattern

These extra patterns mean that Scala patterns support deep matches. Such patterns not only check the top-level object supplied, but also check the contents of the object against further patterns.

Since the extra patterns canthemselvesbeconstructorpatterns,youcanusethemtocheckarbitrarily deep into an object.

For example, the pattern checks that the top-level object is a BinOp, that its third constructor parameter is a Number, and that the value field of that number is 0. This pattern is one line long yet checks three levels deep.

expr match { case BinOp(“+”, e, Number(0)) => println(“a deep match”) case _ => }

scala – pattern match with typed pattern

def generalSize(x: Any) = x match { case s: String => s.length case m: Map[_, _] => m.size case _ => -1 }

The generalSize method returns the size or length of objects of various types. ItsargumentisoftypeAny,soitcouldbeanyvalue. Iftheargumentis a String,themethodreturnsthestring’slength. Thepattern“s: String”is a typed pattern; it matches every (non-null) instance of String. The pattern variable s then refers to that string.

Note that, even though s and x refer to the same value, the type of x is Any, but the type of s is String. So you can write s.length in the alternativeexpressionthatcorrespondstothepattern,butyoucouldnotwrite x.length, because the type Any does not have a length member.

scala – erasure type exception – for arrays

Theonlyexceptiontotheerasureruleisarrays,becausetheyarehandled specially in Java as well as in Scala. The element type of an array is stored with the array value, so you can pattern match on it. Here’s an example:

 

scala> def isStringArray(x: Any) = x match {

case a: Array[String] => “yes”

case _ => “no” } isStringArray: (x: Any)java.lang.String

scala> val as = Array(“abc”) as: Array[java.lang.String] = Array(abc) scala> isStringArray(as) res21: java.lang.String = yes

scala> val ai = Array(1, 2, 3) ai: Array[Int] = Array(1, 2, 3) scala> isStringArray(ai) res22: java.lang.String = no

Scala – Type erasure – ex. Map types

def isIntIntMap(x: Any) = x match { case m: Map[Int, Int] => true case _ => false } <console>:5: warning: non variable type-argument Int in type pattern is unchecked since it is eliminated by erasure case m: Map[Int, Int] => true ˆ

Scalausestheerasuremodelofgenerics,justlikeJavadoes.

Thismeans that no information about type arguments is maintained at runtime.

Consequently, there is no way to determine at runtime whether a given Map object has beencreatedwithtwo Int arguments,ratherthanwithargumentsofdifferent types.

All the system can do is determine that a value is a Map of some arbitrary type parameters.