Skip to main content
deleted 43 characters in body
Source Link
Chris Martin
  • 30.9k
  • 12
  • 83
  • 142

To define custom matching, you need to define an extractor (an object with an unapply method). Implementing that requires parsing the string. Here's some code that does that using parser combinators:

case class StringAndNumber(string: String, number: Int)

object Test {
  def unapply(s: String): Option[StringAndNumber] = Parser(s)
}

object Parser extends scala.util.parsing.combinator.RegexParsers {

  def apply(s: String): Option[StringAndNumber] =
    parseAll(stringAndNumber, s) match {
      case Success(x, _) => Some(x)
      case _ => None
    }

  lazy val stringAndNumber = string ~ number ^^
    { x => StringAndNumber(x._1, x._2) }

  lazy val string = "[^0-9]*".r

  lazy val number = "[0-9]+".r ^^ { _.toInt }
}

def foo(s: String): String = s match {
  case "str" => "str"
  case Test(san) => s"${san.string}, $|${san.number}"
  case _ => "?"
}
 
println {
  Seq(
    foo("str"),  // str
   prints: foo("str2")"str, // strstr|2, 2?"
println ( Seq("str", "str2", "2str").map(foo("2str"_)  // ?
  ).mkString("\n"", ")
} )

To define custom matching, you need to define an extractor (an object with an unapply method). Implementing that requires parsing the string. Here's some code that does that using parser combinators:

case class StringAndNumber(string: String, number: Int)

object Test {
  def unapply(s: String): Option[StringAndNumber] = Parser(s)
}

object Parser extends scala.util.parsing.combinator.RegexParsers {

  def apply(s: String): Option[StringAndNumber] =
    parseAll(stringAndNumber, s) match {
      case Success(x, _) => Some(x)
      case _ => None
    }

  lazy val stringAndNumber = string ~ number ^^
    { x => StringAndNumber(x._1, x._2) }

  lazy val string = "[^0-9]*".r

  lazy val number = "[0-9]+".r ^^ { _.toInt }
}

def foo(s: String): String = s match {
  case "str" => "str"
  case Test(san) => s"${san.string}, ${san.number}"
  case _ => "?"
}
 
println {
  Seq(
    foo("str"),  // str
    foo("str2"), // str, 2
    foo("2str")  // ?
  ).mkString("\n")
}

To define custom matching, you need to define an extractor (an object with an unapply method). Implementing that requires parsing the string. Here's some code that does that using parser combinators:

case class StringAndNumber(string: String, number: Int)

object Test {
  def unapply(s: String): Option[StringAndNumber] = Parser(s)
}

object Parser extends scala.util.parsing.combinator.RegexParsers {

  def apply(s: String): Option[StringAndNumber] =
    parseAll(stringAndNumber, s) match {
      case Success(x, _) => Some(x)
      case _ => None
    }

  lazy val stringAndNumber = string ~ number ^^
    { x => StringAndNumber(x._1, x._2) }

  lazy val string = "[^0-9]*".r

  lazy val number = "[0-9]+".r ^^ { _.toInt }
}

def foo(s: String): String = s match {
  case "str" => "str"
  case Test(san) => s"${san.string}|${san.number}"
  case _ => "?"
}

// prints: "str, str|2, ?"
println ( Seq("str", "str2", "2str").map(foo(_)).mkString(", ") )
Source Link
Chris Martin
  • 30.9k
  • 12
  • 83
  • 142

To define custom matching, you need to define an extractor (an object with an unapply method). Implementing that requires parsing the string. Here's some code that does that using parser combinators:

case class StringAndNumber(string: String, number: Int)

object Test {
  def unapply(s: String): Option[StringAndNumber] = Parser(s)
}

object Parser extends scala.util.parsing.combinator.RegexParsers {

  def apply(s: String): Option[StringAndNumber] =
    parseAll(stringAndNumber, s) match {
      case Success(x, _) => Some(x)
      case _ => None
    }

  lazy val stringAndNumber = string ~ number ^^
    { x => StringAndNumber(x._1, x._2) }

  lazy val string = "[^0-9]*".r

  lazy val number = "[0-9]+".r ^^ { _.toInt }
}

def foo(s: String): String = s match {
  case "str" => "str"
  case Test(san) => s"${san.string}, ${san.number}"
  case _ => "?"
}

println {
  Seq(
    foo("str"),  // str
    foo("str2"), // str, 2
    foo("2str")  // ?
  ).mkString("\n")
}