Search code examples
scalaerror-loggingfor-comprehensionscala-option

How to log None errors in a for-yield block


I have Scala code structured similarly to the following

for {
  item1 <- findItem1
  item2 <- item1.get("item2_info")
} yield {
  val item3 = createItem3(item2)
  if (logic_using_item3) {
    do something here
  }
}

My understanding is in this code if either item1 or item2 resolves to None then the whole chain of execution stops and the yield block isn't executed. You can see that item3 relies on item2 not being None, which it itself relies on item1 not being None.

I want to include error reporting but the best I could come up with while keeping the for-yield block was the following (Note: I'm reasonably new to Scala and functional programming, but realise the following isn't "Good Scala"):

val x = for {
  item1 <- findItem1
  item2 <- item1.get("item2_info")
} yield {
  val item3 = createItem3(item2)
  if (logic_using_item3) {
    do something here
  }
}
if (x == None) {
   logger.error("Something went wrong")
}

What would be the correct "Scala way" to include error logging in this code to reflect something went wrong such as "Item1 was not found" or "Item2 was empty". Can you do this in a for-yield block or will adding error logging require refactoring the code to not use a for-yield block?


Solution

  • The best, IMHO, would be to use an Either instead of an Option to keep the error message.

    val result = for {
      item1 <- findItem1.toRight(left = "Item1 was not found")
      item2 <- item1.get("item2_info").toRight(left = "Item2 was not empty")
      item3 = createItem3(item2)
      if (logic_using_item3) 
    } yield foo
    
    result match {
      case Right(data) => ???
      case Left(error) => logger.error(error)
    }