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)