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.

scala – variable binding pattern

Variablebinding In addition to the standalone variable patterns, you can also add a variable to any other pattern. You simply write the variable name, an at sign (@), and then the pattern. This gives you a variable-binding pattern.

 

expr match {

case UnOp(“abs”, e @ UnOp(“abs”, _)) => e

case _ =>

}

 

thereisavariable-bindingpatternwith e asthevariable and UnOp(“abs”, _) as the pattern. If the entire pattern match succeeds, then the portion that matched the UnOp(“abs”, _) part is made available as variable e. As the code is written, e then gets returned as is.

scala – pattern guard

def simplifyAdd(e: Expr) = e match {

case BinOp(“+”, x, x) => BinOp(“*”, x, Number(2)) case _ => e }

<console>:11: error: x is already defined as value x case BinOp(“+”, x, x) => BinOp(“*”, x, Number(2))

This fails, because Scala restricts patterns to be linear: a pattern variable mayonlyappearonceinapattern. However,youcanre-formulatethematch with a pattern guard

 

def simplifyAdd(e: Expr) = e match { case BinOp(“+”, x, y) if x == y => BinOp(“*”, x, Number(2)) case _ => e }