Search code examples
scalalistdictionaryfor-comprehensionflatmap

How do I convert this ugly one liner into a clean scala for comprehension?


Hey guys I got this ugly thing:

val test = Some(Map("TesT",123))
val keys = test.getOrElse(Map()).keys.map(_.toLowerCase).asInstanceOf[Set[String]]
require(keys.contains("test")

Can I turn it (line #2) into a clean/readable for comprehension?

Here's my attempt:

scala> val keys = for {
     |       map <- test
     |       keys <- map.keys
     |       k <- keys
     | } yield k.toLowerCase
<console>:18: error: value toLowerCase is not a member of Char
       } yield k.toLowerCase
                 ^
<console>:16: error: type mismatch;
 found   : Iterable[Char]
 required: Option[?]
             keys <- map.keys
                  ^

Solution

  • Comprehensions is just a syntactic sugar for map/flatMap. The flatMap method of Option returns another Option. To get a multiple values you should start with sequence, so the first line should be map <- test.toSeq. This explains the second error message.

    The second line in the comprehension try to access keys using flatMap. It could be fixed in two ways. Either replaces it by val keys = map.keys, so neither map or flatMap is involved, or remove this line completely in make a call on the third one: k <- map.keys. This will fix fix the first error.

    So you may choose between two solutions:

    val keys = for {
           map <- test.toSeq
           val keys = map.keys
           k <- keys
     } yield k.toLowerCase
    

    or

     val keys = for {
           map <- test.toSeq
           k <- map.keys
     } yield k.toLowerCase