我發現這個問題有點遲了:)。一種可能性是用輔助函數來包裝=> A
成一個輔助類一起,以簡化其創作:
import scala.language.implicitConversions
class Helper[+A](value: => A) extends Function0[A] {
override def apply(): A = value;
}
object Helper {
def unapply[A](h: Helper[A]): Option[A] = Some(h());
}
implicit def toHelper[A](body: => A) = new Helper(body);
不是必需的提取,它只是允許在助手容易匹配。然後,我們可以寫
def orElse[A](xs: Helper[Option[A]]*): Option[A] =
xs.collectFirst[A]({
case Helper(Some(r)) => r;
})
lazy val o1 = { println("foo"); None }
lazy val o2 = { println("bar"); Some("bar") }
lazy val o3 = { println("baz"); Some("baz") }
orElse(o1, o2, o3) //, ...
這僅僅是一個簡單的解決方案,更現實的是
def orElse[A](x: Option[A], xs: Helper[Option[A]]*): Option[A]
與更有效的實現。
中已經有Scalaz類似Helper
一類,稱爲Name
與實施Need
,確保身體被評爲最多一次。所以與斯卡拉斯,它可以實現爲
import scala.language.implicitConversions
import scalaz._
import scalaz.Scalaz._
implicit def toNeed[A](body: => A): Name[A] = Need(body);
def orElse[A](xs: Name[Option[A]]*): Option[A] =
xs.collectFirst[A]({
case Name(Some(r)) => r;
})
lazy val o1 = { println("foo"); None }
lazy val o2 = { println("bar"); Some("bar") }
lazy val o3 = { println("baz"); Some("baz") }
orElse(o1, o2, o3) //, ...
我試過這在repl,但不幸的是它似乎強制所有三個參數。 – 2009-12-01 16:24:54
你是對的隱式類型轉換迫使評估。我修復了代碼。 – 2009-12-01 16:58:38