Scala - case match partial string
Asked Answered
A

4

36

I have the following:

serv match {

    case "chat" => Chat_Server ! Relay_Message(serv)
    case _ => null

}

The problem is that sometimes I also pass an additional param on the end of the serv string, so:

var serv = "chat.message"

Is there a way I can match a part of the string so it still gets sent to Chat_Server?

Thanks for any help, much appreciated :)

Antislavery answered 19/3, 2012 at 12:42 Comment(3)
As can be seen below, there are solutions. But maybe serv wants to be a more structured value and not just a simple String?Disincentive
a case class would be perfect for this!Smythe
The use of null should be avoided in Scala; use Option instead. null really only exists for interoperability with Java.Embolic
B
57

Use regular expressions, make sure you use a sequence wildcard like _*, e.g.:

val Pattern = "(chat.*)".r

serv match {
     case Pattern(_*) => "It's a chat"
     case _ => "Something else"
}

And with regexes you can even easily split parameter and base string:

val Pattern = "(chat)(.*)".r

serv match {
     case Pattern(chat, param) => "It's a %s with a %s".format(chat, param)
     case _ => "Something else"
}
Behr answered 19/3, 2012 at 12:49 Comment(6)
in your case, the "chat" variable in the pattenr matching is clearly useless, you can replace it with Pattern(_)Homy
@Homy yes, you're right. I've not ommited it cause in op version chat would be used as a message to server.Behr
Beware, in your solution, chat variable will always be equal to "chat" if the pattern matched. (that's why I wrote that it was useless)Homy
@Homy Oh, I've modified pattern. Now it will grab rest of the string too.Behr
The regex will fail to match if there's a newline in the message part.Genseric
Thanks alot, went with your suggestion as I can easily access the extra param passed :)Antislavery
S
55

Have the pattern matching bind to a variable and use a guard to ensure the variable begins with "chat"

// msg is bound with the variable serv
serv match {
  case msg if msg.startsWith("chat") => Chat_Server ! Relay_Message(msg)
  case _ => null
}
Smythe answered 19/3, 2012 at 12:48 Comment(3)
It is so called guard in the first case expressionBehr
Kyle's answer is perfect and still relevant to modern scala. You could also use msg.contains("chat") if you want to match something like "message.chat". It's another way of guarding. Thanks Kyle.Pascale
Please specify what is msg and what do you mean by "pattern matching bing to a variable"Comstock
B
2

In case you want to dismiss any groupings when using regexes, make sure you use a sequence wildcard like _* (as per Scala's documentation).

From the example above:

val Pattern = "(chat.*)".r

serv match {
     case Pattern(_*) => "It's a chat"
     case _ => "Something else"
}
Benzol answered 16/12, 2018 at 3:14 Comment(0)
M
0

Since Scala 2.13, you can use the s interpolator in a match

serv match {
  case s"chat" => ...
  case s"chat.$msg" => doSomething(msg)
  ...
}
Melanochroi answered 8/11, 2023 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.