Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matching case classes in scala: ~(a,b) match{case a~b=>...}

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?

like image 588
stub Avatar asked Jul 14 '10 12:07

stub


People also ask

What is Scala match case?

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.

What are case classes in Scala?

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.

What is case class and pattern matching in Scala?

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.


1 Answers

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 :: NilNil.::(3), as

val l: List[Int] = ( ( Nil.::(3) ).::(2) ).::(1)
like image 87
Debilski Avatar answered Sep 28 '22 07:09

Debilski