Is it possible to rewrite the following code using Scala pattern matching?
val ls: List[String] = ??? // some list of strings
val res = if (ls.contains("foo")) FOO
else if (ls.contains("bar")) BAR
else SOMETHING_ELSE
Pattern matching tests whether a given value (or sequence of values) has the shape defined by a pattern, and, if it does, binds the variables in the pattern to the corresponding components of the value (or sequence of values). The same variable name may not be bound more than once in a pattern.
Pattern matching is the second most widely used feature of Scala, after function values and closures. Scala provides great support for pattern matching, in processing the messages. A pattern match includes a sequence of alternatives, each starting with the keyword case.
Pattern matching is a mechanism for checking a value against a pattern. A successful match can also deconstruct a value into its constituent parts. It is a more powerful version of the switch statement in Java and it can likewise be used in place of a series of if/else statements.
case _ => does not check for the type, so it would match anything (similar to default in Java). case _ : ByteType matches only an instance of ByteType . It is the same like case x : ByteType , just without binding the casted matched object to a name x .
You can add if
conditions to matches like this:
ls match {
case x if x.contains("foo") => // FOO
case x if x.contains("bar") => // BAR
case _ => // ELSE
}
However, it is not the nicest way, as each if
check needs to traverse the list, so this doesn't scale well. There are various different ways to deal with this problem, but we would need to know more about your intensions, as normally the runtime semantics would differ from your code (for example, you could recursively traverse the list looking for either "foo" or "bar", but that would assume you only have either one in the list).
You could implement this using a function like
def onContains[T](xs: Seq[String], actionMappings: (String, T)*): Option[T] = {
actionMappings collectFirst {
case (str, v) if xs contains str => v
}
}
And use it like this:
val x = onContains(items,
"foo" -> FOO,
"bar" -> BAR
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With