2012-07-06 82 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