cool breeze
cool breeze

Reputation: 4811

Yielding from a for-comp is not returning the type I want

Why is the return value a Try[Serializable] for the val maybeString? I want it to be an Option[String]

import scala.util.Try

val a1 = Try("fase".toBoolean)
val b2 = Try("100".toInt)

val maybeString: Option[String] = for {
  a <- a1
  b <- b2
} yield (a,b) match {
  case (true, 50) => "foo"
  case (false, 100) => "bar"
  case _ => None
}

println(s"string is $maybeString")

Upvotes: 0

Views: 51

Answers (2)

Victor Moroz
Victor Moroz

Reputation: 9225

You may not need to convert to Option until the very last moment:

val maybeString: Option[String] = 
  ( for {
    a <- a1
    b <- b2
    s <- Try(
        (a, b) match {
          case (true, 50) => "foo"
          case (false, 100) => "bar"
        }
      )
  } yield (s)).toOption

Here I extract a and b (if they are both successful) and the result of for comprehension has a type Try[String]. Then I can easily convert it to Option[String].

UPDATE

Covered the case when (a, b) doesn't match

Upvotes: 1

tkachuko
tkachuko

Reputation: 1986

Why is the return value a Try[Serializable] for the val maybeString?

Because scala compiler cannot determine the type of the element you return in the following expression:

(a,b) match {
  case (true, 50) => "foo"
  case (false, 100) => "bar"
  case _ => None
}

You return String in two cases and Option (i.e. None) in another one, so it picks up the most common type in hierarchy: Serializable.

I want it to be an Option[String]

object Test extends App {

  import scala.util.Try

  val a1 = Try("false".toBoolean)
  val b2 = Try("100".toInt)

  val maybeString: Option[String] = for {
    a <- a1.toOption
    b <- b2.toOption
  } yield (a, b) match {
    case (true, 50) => "foo"
    case (false, 100) => "bar"
  }

  println(s"string is $maybeString")
}

Upvotes: 3

Related Questions