46

How can I get the default value in match case?

//Just an example, this value is usually not known
val something: String = "value"

something match {
    case "val" => "default"
    case _ => smth(_) //need to reference the value here - doesn't work
}

UPDATE: I see that my issue was not really understood, which is why I'm showing an example which is closer to the real thing I'm working on:

val db =    current.configuration.getList("instance").get.unwrapped()
            .map(f => f.asInstanceOf[java.util.HashMap[String, String]].toMap)
            .find(el => el("url").contains(referer))
            .getOrElse(Map("config" -> ""))
            .get("config").get match {
                case "" => current.configuration.getString("database").getOrElse("defaultDatabase")
                case _  => doSomethingWithDefault(_)
            }
Caballero
  • 11,546
  • 22
  • 103
  • 163
  • 3
    Not sure, you mean this maybe? `case _ => smth(something)` – David Riccitelli Nov 22 '13 at 15:34
  • @DavidRiccitelli that `something` comes from a very long sequence of actions which is why I need another way to reference it – Caballero Nov 22 '13 at 15:42
  • To understand better, are you trying to pass `something` to `smth` when `something` is not equal to `val`? (as an example) – David Riccitelli Nov 22 '13 at 15:44
  • Ok, you could split to make it also readable - as Martin O. says :-) – David Riccitelli Nov 22 '13 at 15:47
  • 1
    `val config = current.configuration.getList("instance").get.unwrapped() .map(f => f.asInstanceOf[java.util.HashMap[String, String]].toMap) .find(el => el("url").contains(referer)) .getOrElse(Map("config" -> "")) .get("config").get` and then `config match ....` – David Riccitelli Nov 22 '13 at 15:47
  • @DavidRiccitelli For some reason (from examples I've seen) I thought that the point of functional programming is to do everything in one go, that is without creating intermediate variables? – Caballero Nov 22 '13 at 15:49
  • 2
    nope it's not ... I'll try to get the speech from Martin Odersky where he specifically tells: "don't do one liners" :-) – David Riccitelli Nov 22 '13 at 15:51
  • 1
    @Caballero not necessarily, readability wins, always =) – abronan Nov 22 '13 at 15:53
  • 1
    There we go, http://www.youtube.com/watch?v=kkTFx3-duc8, minute 15 onwards "Don't pack too much as an expression". – David Riccitelli Nov 22 '13 at 15:54
  • I don't have a problem with the expr chain per se, but the cast is suspicious (as always), and I think the extra get can be avoided by flatmapping the result of the find and if you wind up with None, do the fallback at the end. That's just on principle of deferring the get as long as you can. – som-snytt Nov 23 '13 at 02:13

3 Answers3

66
something match {
    case "val" => "default"
    case default => smth(default)
}

It is not a keyword, just an alias, so this will work as well:

something match {
    case "val" => "default"
    case everythingElse => smth(everythingElse)
}
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • 1
    or if you don't need to use the variable, it can be anonymous: case _ => doSomething – Jeroen Kransen Nov 22 '13 at 16:05
  • 4
    @JeroenKransen your proposition is exactly equals to what op started from – om-nom-nom Nov 22 '13 at 16:16
  • 1
    I didn't understand the valid question either. There was a similar recent question, How do I refer to _ in an anon function. Maybe it's like one of those optical illusion puzzles. – som-snytt Nov 23 '13 at 02:18
23

The "_" in Scala is a love-and-hate syntax which could really useful and yet confusing.

In your example:

something match {
    case "val" => "default"
    case _ => smth(_) //need to reference the value here - doesn't work
}

the _ means, I don't care about the value, as well as the type, which means you can't reference to the identifier anymore. Therefore, smth(_) would not have a proper reference.
The solution is that you can give the a name to the identifier like:

something match {
    case "val" => "default"
    case x => smth(x)
}

I believe this is a working syntax and x will match any value but not "val".

More speaking. I think you are confused with the usage of underscore in map, flatmap, for example.

val mylist = List(1, 2, 3)
mylist map { println(_) }

Where the underscore here is referencing to the iterable item in the collection. Of course, this underscore could even be taken as:

mylist map { println } 
Joyfulvillage
  • 547
  • 1
  • 4
  • 13
  • Actually it is not only the Scala thing -- the underscode-for-things-I-don't care is used in SML, Clojure and some other languages. – om-nom-nom Nov 22 '13 at 18:43
3

here's another option:

something match {
    case "val" => "default"
    case default@_ => smth(default)
}
Paul Richter
  • 10,908
  • 10
  • 52
  • 85
Dan
  • 386
  • 4
  • 10
  • 6
    For those like me who'd either never seen or forgotten this: see [Scala @ operator](http://stackoverflow.com/questions/2359014/scala-operator) – Ed Staub Feb 27 '15 at 18:49