奇怪的折叠范围问题

时间:2012-07-06 00:34:10

标签: scala fold scoping

我在调试事务查询块时碰到了这个头颅。

出于某种原因,尽管折叠左/失败操作中发生了连接回滚,但成功/正确的结果也会被回滚。

示例:

// 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(_) )

1 个答案:

答案 0 :(得分:4)

考虑以下稍微简单的例子:

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

每次调用foo时,导弹都会启动,因为我们传递的第一个参数并不完全是一个函数:它是一个计算函数的块,并且该块将被评估是否使用该功能。

请参阅Jesse Eichar的this blog post,了解有关此行为的更详细讨论。