Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala polymorphic function for filtering an input List of Either

Seeking a more elegant solution

I have this piece of code, I just use it in test cases where it isn't necessary to do any error handling. What it does is:

  • take an input list of strings
  • parse them using the DSJSonmapper.parseDSResult method
  • filters them and extracts the Right value from each Either (Left is an Exception)

The code is as follows:

  def parseDs(ins: List[String]) = {
    def filterResults[U, T](in: List[Either[U, T]]): List[T] = {
      in.filter(y => y.isRight).map(z => z.right.get)
    }
    filterResults(ins.map(x => DSJsonMapper.parseDSResult(x)))
  }

Now, I haven't done an awful lot of polymorphic functions, but this works. However I feel like it's a bit ugly. Has anyone got a better suggestion, how to accomplish the same thing.

I'm aware this is going to come down to a case of personal preference. But suggestions are welcome.

like image 712
Bryan Hunt Avatar asked Aug 08 '12 15:08

Bryan Hunt


2 Answers

collect is made for exactly this kind of situation:

def filterMe[U,T](in: List[Either[U,T]]): List[T] = in.collect{
  case Right(r) => r
}

In fact, it's so good at this you may want to skip the def and just

ins.map(DSJsonMapper.parseDsResult).collect{ case Right(r) => r }
like image 55
Rex Kerr Avatar answered Nov 19 '22 17:11

Rex Kerr


Rex's answer is possibly a little clearer, but here's a slightly shorter alternative that parses and "filters" in a single step:

ins.flatMap(DSJsonMapper.parseDSResult(_).right.toOption)

Here we take the right projection of each parse result and turn that into an Option (which will be None if the parse failed and Some(whatever) otherwise). Since we're using flatMap, the Nones don't appear in the result and the values are pulled out of the Somes.

like image 42
Travis Brown Avatar answered Nov 19 '22 18:11

Travis Brown