We’ve already seen how to extract primitive types and tuples from regular expression matches, but a more common requirement is to extract case classes - often preferable to tuples, since they provide more meaningful types.
Let’s take the following input and attempt to extract the bits between brackets:
val input = "(1, 2) and (3, false)"
This could be achieved with the following regular expression:
import kantan.regex.implicits._
val regex = rx"\((\d+), (\d+|true|false)\)"
And since we’re trying to demonstrate case class extraction, let’s extract data to the following case class:
case class WeirdPoint(x: Int, y: Either[Int, Boolean])
In order to extract complex (as in, composed of more than one value) types, we need to provide instances of
MatchDecoder
for them. We can create a new one with one of MatchDecoder
’s many helper methods - ordered
,
in our case, since match groups and case class fields are in the same order:
import kantan.regex._
implicit val decoder: MatchDecoder[WeirdPoint] = MatchDecoder.ordered(WeirdPoint.apply _)
And that’s all there is to it. Now that we have this decoder in place, we can just call evalRegex
as usual:
input.evalRegex[WeirdPoint](regex).foreach(println _)
// Right(WeirdPoint(1,Left(2)))
// Right(WeirdPoint(3,Right(false)))
It’s possible to automate this process through the shapeless-backed generic module. Let’s first import the module and declare a new case class:
import kantan.regex.generic._
case class Foo(x: Int, y: Either[Int, Boolean])
And without any further work, we can decode instances of Foo
:
input.evalRegex[Foo](regex).foreach(println _)
// Right(Foo(1,Left(2)))
// Right(Foo(3,Right(false)))