I have a case class
case class ~[a,b](_1:a, _2:b)
When I want to do pattetn matching
new ~("a", 25) match{
case "a" ~ 25 =>
}
I can use it this way because "a" ~ 25
and ~("a", 25)
are equivalent. But if I want to match new ~("a", new ~("b", 25))
by {case "a" ~ "b" ~ 25 => }
troubles begin. I understand that this statements aren't equivalent. So, how new ~("a", new ~("b", 25))
can be presented? By what rules?
It is the most widely used feature in Scala. It is a technique for checking a value against a pattern. It is similar to the switch statement of Java and C. Here, “match” keyword is used instead of switch statement. “match” is always defined in Scala's root class to make its availability to the all objects.
Scala case classes are just regular classes which are immutable by default and decomposable through pattern matching. It uses equal method to compare instance structurally. It does not use new keyword to instantiate object. All the parameters listed in the case class are public and immutable by default.
Scala's pattern matching statement is most useful for matching on algebraic types expressed via case classes. Scala also allows the definition of patterns independently of case classes, using unapply methods in extractor objects.
This works:
new ~("a", new ~("b", 25)) match {
case "a" ~ ("b" ~ 25) =>
}
So, you’ll have to put the parentheses the same way they are in the initial clause. Otherwise the tilde is left-associative, therefore the type of the pattern will be different and it won’t compile.
case "a" ~ "b" ~ 25
is the same as
case ("a" ~ "b") ~ 25
which would be wrong in your case.
Appendix
You can get right-associativity by having a colon as the last character in your class/method name. The following compiles and matches without parentheses (and you can drop the new
as the compiler won’t be confused anymore by $tilde$colon
):
case class ~:[a,b](_1:a, _2:b)
~:("a", ~:("b", 25)) match {
case "a" ~: "b" ~: 25 =>
}
Responses
1) Without the new
keyword, the case class ~
is shadowed by unary_~
which gives the bitwise negation of the argument. An expression like ~ 2
is internally evaluated to unary_~(2)
and the same goes for the case of ~ ("a", 1)
– however unless you define unary_~
on that tuple, this will give an error. With the new
keyword you advise the compiler to explicitly look for a class with that name, so it won’t get confused.
(Technically, you could work around this by using $tilde("a", 1)
which is the internal name for your case class ~
, but since this is a compiler detail, you should probably not rely on it.)
2&3) The right-associativity is referenced in the Scala Language Specification. Section ‘Infix Operations’
The associativity of an operator is determined by the operator’s last character. Operators ending in a colon ‘:’ are right-associative. All other operators are left-associative.
By the way, right-associativity is the trick that allows for creating lists with Nil
. (Nil
is the empty List
and has the right-associative concatenation operator ::
defined.)
val l: List[Int] = 1 :: 2 :: 3 :: Nil
which is evaluated as follows
val l: List[Int] = (1 :: (2 :: (3 :: Nil)))
or, more precisely, since 3 :: Nil
≡ Nil.::(3)
, as
val l: List[Int] = ( ( Nil.::(3) ).::(2) ).::(1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With