4

Say I have a class with multiple parameters:

case class Foo(a: String, b: String, c: String, d: String, ... )

Now say I want to parse an instance of Foo from a Map[String, String]:

// returns either the parsed Foo as Right, or error message as Left
// example: Map("a" -> "1", "b" -> "2" ... ) returns Foo("1", "2", ... )
def parse(fromMap: Map[String, String]): Either[String, Foo]

The names of the keys are irrelevant; this is not a reflection type of question.

My implementation looks something like this:

fromMap.get("a") match {
    case None => Left("couldn't find a")
    case Some(a) => fromMap.get("b") match {
        ...
                                case Some(last) => Right(Foo(a, ... , last))
    }
}

But when there are many parameters, the indentation is just too extreme, and that makes it hard to understand the logic of the method (it may be a bit more complex than just a map lookup).

Can you think of a more readable code for such a use-case?

1 Answer 1

6

You could create your custom method for extracting Map values as an Either instance and use them in a for comprehension:

implicit final class MapOps[A, B](self: Map[A, B]) {
  def getAsEither(key: A): Either[String, B] = {
    self.get(key) match {
      case Some(value) => Right(value)
      case _ => Left(s"Key not found: $key")
    }
  }
}

case class Foo(a: String, b: String, c: String, d: String)

def parse(input: Map[String, String]): Either[String, Foo] = {
  for {
    a <- input.getAsEither("a").right
    b <- input.getAsEither("b").right
    c <- input.getAsEither("c").right
    d <- input.getAsEither("d").right
  } yield Foo(a, b, c, d)
}

This could be shortened a little (all those .right invocations could be removed) but would require using right-biased implementations of the Either (e.g. Scala'z \/ or Cats' Xor)

1
  • I pretty much dislike implicit and I don't see the need for the implicit Map here; passing it as an argument to getAsEither still persists the readable indentation. Other than that, the for-comprehension is a neat solution, thanks!
    – Eyal Roth
    Commented May 25, 2016 at 9:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.