2012-07-06 84 views
1

我在调试事务查询块时遇到了这个头部划伤器。奇怪的折叠范围问题

由于某些原因,尽管在折叠左/失败操作中发生连接回滚,成功/正确结果也得到回滚。

例子:

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

回答

4

考虑以下稍微简单例子:

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

导弹会得到展开每次调用foo时间,因为我们传递的第一个参数是不正是一个函数:它是一个评估函数的块,并且该块将被评估是否使用该函数。

参见Jesse Eichar的this blog post关于这种行为的更详细讨论。

+0

+1事实上,不仅会发射导弹,还会发送来自愤怒客户的现代信件;-)我感到困惑至少说,但现在我知道,折叠块的参数化是必须的。感谢你的线索...... – virtualeyes 2012-07-06 01:57:16