私は少し遅れて質問を見つけました:)。=> A
1 つの可能性は、ヘルパー関数と共にヘルパー クラスにラップして、その作成を簡素化することです。
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]
より効率的な実装で。
Helper
Scalaz に似たクラスが既にあり、本体が最大 1 回評価されることを保証するName
実装で呼び出されます。Need
したがって、Scalaz では次のように実装できます。
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) //, ...