1
votes

This works

val keys Option[List[Option[String]]] = someFunctionThatReturnsKeys()
val tries = for (
    unwrapped <- keys) {
        for(keyOption <- unwrapped;
            stripped <- keyOption if stripped.contains(":")) 
        yield Try(java.lang.Long.parseLong(stripped.substring(stripped.lastIndexOf(":") + 1)))         }

This does not work.

val tries = for (
              unwrapped <- keys;
              keyOption <- unwrapped;
               stripped <- keyOption if stripped.contains(":")) 
            yield Try(java.lang.Long.parseLong(stripped.substring(stripped.lastIndexOf(":") + 1)))

The error is for the line

keyOption <- unwrapped;

The error is displayed as

type mismatch; found : List[scala.util.Try[Long]] required: Option[?]

I am using eclipse ide with scala 2.10

Why is the type inference failing?

1

1 Answers

1
votes

Type inference isn't failing, it's that the for desugars into a flatMap, and Option doesn't know how to flatten anything but another Option.

What do you want the return type to be? That will determine what you actually want to do. For instance, if you want a list:

val tries = for {
  unwrapped <- keys.toList;
  keyOption <- unwrapped;
  stripped <- keyOption if stripped.contains(":")
} yield Try(stripped.substring(1 + stripped.lastIndexOf(":")).toLong)

will do the trick. You'll get a List[Try[Long]], which will be empty if the outer Option was None.

If you want to keep the outer option, you really want a map not a flatMap at the outside, which is more easily written like so:

val tries2 = keys.map(unwrapped => for {
  keyOption <- unwrapped;
  stripped <- keyOption if stripped.contains(":")
} yield Try(stripped.substring(1 + stripped.lastIndexOf(":")).toLong))

This will give you an Option[List[Try[Long]]].