Extracting case classes

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

Other tutorials: