38

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 :)

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? Commented Mar 19, 2012 at 13:00
  • 3
    a case class would be perfect for this! Commented Mar 19, 2012 at 13:12
  • 7
    The use of null should be avoided in Scala; use Option instead. null really only exists for interoperability with Java. Commented Mar 19, 2012 at 13:43

4 Answers 4

59

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"
}
Sign up to request clarification or add additional context in comments.

6 Comments

in your case, the "chat" variable in the pattenr matching is clearly useless, you can replace it with Pattern(_)
@Nicolas yes, you're right. I've not ommited it cause in op version chat would be used as a message to server.
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)
@Nicolas Oh, I've modified pattern. Now it will grab rest of the string too.
The regex will fail to match if there's a newline in the message part.
|
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
}

3 Comments

It is so called guard in the first case expression
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.
Please specify what is msg and what do you mean by "pattern matching bing to a variable"
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"
}

Comments

1

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

serv match {
  case s"chat" => ...
  case s"chat.$msg" => doSomething(msg)
  ...
}

2 Comments

How'd you use this to match a string head and tail, like we can do on Seq?
You can't. The s interpolator is convenient for doing certain simple jobs, but it's not a jack of all trades. Consider using another approach such as a regex match or calling .head and .tail directly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.