0

I am new to Scala,

For every key in a map, I want to match a new value

class SomeLongNameObject {
    val m: Map[String, String] = Map("a" -> "aa",
      "b" -> "bb",
      "other" -> "someString")

    m.map {
      case (aKey, v) => println("a found")
      case (bKey, v) => println("b found")
      case (k,v) => println("fallback")
    }
  }

  object SomeLongNameObject {
    val aKey = "a"
    val bKey = "b"
  }
  val someObject = new SomeLongNameObject

I expect (and desire) that the given map will print

a found

b found

fallback

however, the result is

a found

a found

a found

As I understand the aKey from the SomeLongNameObject object not used in the case (aKey, v), Is there a way to force it to use the vals from the object SomeLongNameObject in a more elegant way than below?

m.map {
      case (SomeLongNameObject.aKey, v) => println("a found")
      case (SomeLongNameObject.bKey, v) => println("b found")
      case (k,v) => println("fallback")
    }

1 Answers1

2

When you write case (aKey, v) => ... that means "deconstruct the tuple, and assign the first element to a local variable aKey, and the second element to local variable b. It does not matter whether variables with the same name are already in scope (which in your case they actually aren't, you need to import SomeLongNameObject._ to bring them in)

One way to tell the compiler you are actually talking about matching to the value of a variable not just assignment is using backticks:

    case (`aKey`, v) => ???

would work if aKey was in scope.

Another way, is to exploit a "secret feature": if a variable name starts with a capital letter, you don't need backticks :) If instead of aKey, you had just A, this would work: case (A, v) => ???

Yet another way is using a guard condition:

   case (k,v) if k == aKey => ???

Finally, the solution you found yourself: case (SomeLongNameObject.aKey, v) => is actually quite fine. I personally would rather stick with this approach, just change the name of the object to something meaningful but short (which I would probably do either way – I hate long names with passion), or at least, use an alias:

   val keys = SomeLongNameObject
   foo foreach { 
      case (keys.aKey, _) => ???
      ...
Dima
  • 39,570
  • 6
  • 44
  • 70