Frage

I ran into this head scratcher while debugging a transactional query block.

For some reason, despite the connection rollback occurring in the fold left/fail operation, success/right outcomes were getting rolled back as well.

Example:

// returns Either[String, Int]
db.handle withSession { implicit ss: Session=>
  ss.withTransaction {
    val result = for {
      u  <- either(User.insert(User(model)), ss)
      ur <- either(UserRole.insert( UserRole(u) ), ss)
      m  <- either(Membership.insert(Membership(u)), ss)
    } yield u

// bad: rollback occurs regardless of left/right outcome
result fold( {ss.rollback; Left(_)}, Right(_) )

// good: rollback occurs as expected on left outcome only
result fold( e=>{ss.rollback; Left(e)}, Right(_) )
War es hilfreich?

Lösung

Consider the following slightly simpler example:

def foo[A, B](e: Either[A, B]) = e.fold(
  { println("Launch the missiles!"); Left(_) },
  Right(_)
)

Missiles are going to get launched every time you call foo, because the first argument we're passing isn't exactly a function: it's a block that evaluates to a function, and that block's going to get evaluated whether or not the function is used.

See this blog post by Jesse Eichar for a more detailed discussion of this behavior.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top