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?

asked May 23, 2016 at 17:23

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)

answered May 23, 2016 at 18:28
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! Commented May 25, 2016 at 9:37

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.