Home > Enterprise >  Pattern matching on a Scala case class with `type` as a field
Pattern matching on a Scala case class with `type` as a field

Time:08-24

I have a case class defined for JSON parsing using the Circe library:

  final case class Event(
    source: Option[String],
    nonce: Option[Int],
    `type`: Option[Any],
    tag: Option[String],
    payload: Option[Any],
    blockOrder: Option[Int] = None,
    metadata: ResultMetadata[OperationResult.Event]
  ) extends Operation

Note that one of the fields is called type and I can only use the name using backticks or I get a compiler error. I don't have any choice over the schema used by the source system supplying the data.

Later on, when I try to pattern match on the case class in order to write some information to a database...

private val convertEvent: PartialFunction[
    (Block, OperationHash, Operation),
    Tables.OperationsRow
  ] = {
    case (
      block,
      groupHash,
      Event(source, nonce, `type`, tag, payload, blockOrder, metadata)
      ) =>
    ...

...I get the following error:

not found: value type
      Event(source, nonce, `type`, tag, payload, blockOrder, metadata).

Is there any way I can still use Circe and case classes in general when a field has the same name as a reserved keyword?

CodePudding user response:

In 2.13.8 the error is

not found: value type
Identifiers enclosed in backticks are not pattern variables but match the value in scope.
      Event(source, nonce, `type`, tag, payload, blockOrder, metadata)

so just use something different from type in pattern matching as a pattern variable.

For example

case (
  block,
  groupHash,
  Event(source, nonce, typ, tag, payload, blockOrder, metadata)
  ) =>

CodePudding user response:

That's because backticks in pattern matching mean to use an already-existing value accessible in the scope, to check the equity of a pattern variable, like this:

case class Person(name: String, age: Int)
val johnName = "John"
val john = Person(johnName, 99)
val alice = Person("Alice", 128)

john match {
  case Person(`johnName`, someAge) => 
    // this will be matched, sine johnName = "John"
}

alice match {
  case Person(`johnName`, someAge) => 
    // won't match, "Alice" != "John"
  case Person(johnName, someAge) => 
    // this one matches, since johnName in the pattern is only some alias,
    //  and will shadow the variable defined above 
}

The solution/workaround is already mentioned in the other anwer.

  • Related