5

Fields (vals) of class instances could be used while pattern matching:

class A {
  val foo = 37
  def bar = 42
}

def patmat1(a: A, x: Int) {
  x match {
    case a.foo => println("a.foo")
    case _     => println("not a.foo")
  }
}

patmat1(new A, 37) // => a.foo
patmat1(new A, 42) // => not a.foo

And I wonder why def cannot be used analogously?

def patmat2(a: A, x: Int) {
  x match {
    case a.bar => println("a.bar")
    //     ^ error: stable identifier required, but a.bar found.
    case _     => println("not a.bar")
  }
}

I thought that val and def are mostly interchangeable.

2 Answers2

2

Well as per reference, your second case is not a valid pattern. val foo works because it is a Stable Identifier Pattern § 8.1.5 which basically means that it checks if x == a.foo.

Your second case is simply not any valid pattern (as a.bar is not a identifier but a declaration) hence the error.

One idiomatic way would be:

def patmat1(a: A, x: Int) {
  x match {
    case i if a.bar == x => println("a.foo")
    case _     => println("not a.foo")
  }
} 
Jatin
  • 31,116
  • 15
  • 98
  • 163
0

I believe the first part of the left-half of a case statement is to destructure an object or match it to a constant value. So, for example:

val animal: Animal = Dog("butch",4)

animal match {
  case _: Dog => println("bow-wow")
  case _: Cat => println("meow")
}

If you want to compare to a constant, you can do that in the main part of the case statement:

secretConstant match {
  case Math.PI => println("I'm a PI")
  case Math.E  +> println("I'm an E")
  case _ => println("I don't know what I am")
}

But if you want to compare against a calculated value, then you need to include it within the if portion of a case statement:

tomsWeddingDate match {
  case date: LocalDate if date < LocalDate.now() => println("phew, I still have time to buy a gift.")
  case _ => println("Oops, I guess I need to send a belated card")
}
Alex
  • 1,470
  • 1
  • 11
  • 28