manonthemat
manonthemat

Reputation: 6251

Scala Regex pattern matching issue when using |

This is my example code.

object Patterns {
  val workingPattern = """^thisworks[\w]+""".r
  val problemPattern = """^(fail|error|bs|meh)[\w]+""".r
}                                                                                                                                                                           

object TestMaker {
  var works = scala.collection.mutable.Set[String]()
  var needsWork = scala.collection.mutable.Set[String]()
  var junk = scala.collection.mutable.Set[String]()
  def add(someInput: String) = someInput match {                                                                                                                                      
    case Patterns.workingPattern() => works.update(someInput, true)
    case Patterns.problemPattern() => needsWork.update(someInput, true)
    case _ => junk.update(someInput, true)                                                                                                                                       
  }
}

When I call TestMaker.add("thisworks1234"), the string "thisworks1234" gets inserted into TestMaker's works set. It works as expected.

When I call TestMaker.add("this_is_just_junk"), the string "this_is_just_junk" gets inserted into the junk set - also as expected.

Here's the problem. When I call TestMaker.add("fail1234"), that string will also be inserted into the junk set. It should however be inserted into the needsWork set.

Where's my mistake?

Upvotes: 1

Views: 40

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626903

You should use a non-capturing group with the second regex:

val problemPattern = """^(?:fail|error|bs|meh)[\w]+""".r
                         ^^^

This is required because you are not referencing the captured value in your case.

Note that you can still use capturing groups within your patterns to ignore them later while matching with _*:

case Patterns.workingPattern(_*) => works.update(someInput, true)
case Patterns.problemPattern(_*) => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)     

See the IDEONE demo:

object Main extends App {
    TestMaker.add("this_is_just_junk")
    TestMaker.add("fail1234")
    println(TestMaker.needsWork) // => Set(fail1234)
    println(TestMaker.junk)      // => Set(this_is_just_junk)
}
object Patterns {
  val workingPattern = """^thisworks[\w]+""".r
  val problemPattern = """^(fail|error|bs|meh)[\w]+""".r
}  
object TestMaker {
  var works = scala.collection.mutable.Set[String]()
  var needsWork = scala.collection.mutable.Set[String]()
  var junk = scala.collection.mutable.Set[String]()
  def add(someInput: String) = someInput match {                                                                                                                                      
    case Patterns.workingPattern(_*) => works.update(someInput, true)
    case Patterns.problemPattern(_*) => needsWork.update(someInput, true)
    case _ => junk.update(someInput, true)    
  }
}

Upvotes: 1

Related Questions