4

Ok, so this sounds like a trivial question.

  val delim = ','
  val chars = "abc,def".toCharArray
  var i = 0
  while (i < chars.length) {
    chars(i) match {
      case delim =>
        println(s"($i): D!")
      case c =>
        println(s"($i): $c")
    }
    i += 1
  }

I'm baffled that the output of this is:

(0): D!
(1): D!
(2): D!
(3): D!
(4): D!
(5): D!
(6): D!

I expected this:

(0): a
(1): b
(2): c
(3): D!
(4): d
(5): e
(6): f

How can I match on a Char value?

NOTE: If I hardwire the delim char "case ',' =>" instead, it works as expected! Why does it break if I use a Char-typed val?

jwvh
  • 50,871
  • 7
  • 38
  • 64
Greg
  • 10,696
  • 22
  • 68
  • 98
  • 4
    Possible duplicate of [Why does pattern matching in Scala not work with variables?](https://stackoverflow.com/questions/7078022/why-does-pattern-matching-in-scala-not-work-with-variables) – Luis Miguel Mejía Suárez Apr 01 '19 at 20:38

1 Answers1

9

Your pattern match is creating a 2nd variable called delim that shadows the 1st, and since a new and unadorned variable matches everything, that's the only case that gets executed.

Use back-tics to tell the compiler to match against the existing variable, not a new one.

  case `delim` =>
jwvh
  • 50,871
  • 7
  • 38
  • 64
  • Also, `final val Delim = ','`, works. Note the **UpperCase** and the _final_. – Luis Miguel Mejía Suárez Apr 01 '19 at 20:35
  • 1
    @LuisMiguelMejíaSuárez Just upper case would be enough. All `val`s are final, you don't need to add it, it's redundant and confusing. – Dima Apr 01 '19 at 21:24
  • 1
    @Dima val doesn't mean the field is final. If the field is final it can't be overridden in subclass and vals can be. – Krzysztof Atłasik Apr 01 '19 at 22:27
  • 1
    @KrzysztofAtłasik yeah, I assumed this was just a local variable. – Dima Apr 01 '19 at 22:47
  • @Dima on some cases the compiler requires that the `val` to be _final_ in order to pattern match them. I believe _(not 100% sure though)_ that is when the val could be overridden. So, I just always use _final_. – Luis Miguel Mejía Suárez Apr 01 '19 at 23:31
  • @LuisMiguelMejíaSuárez I dunno. Show me one of those "cases". `class Foo { val Bar = "bar"; def foo(x: String) = x match { case Bar => "foo" } }` works fine for me. AS WELL AS `class Bar extends Foo { override val Bar = "foo" }`. And in general I see nothing wrong with being able to override the value. – Dima Apr 02 '19 at 10:53
  • @Dima Yes, you are correct, I was confused. You need the _final_ if you want to [ensure that the `match` to be compiled to a _switch_](https://www.scala-lang.org/api/current/scala/annotation/switch.html). [See this SO question](https://stackoverflow.com/questions/12309114/why-is-a-val-inside-an-object-not-automatically-final). - So, yes, in general you are right, you only need the **UpperCase**. – Luis Miguel Mejía Suárez Apr 02 '19 at 14:50