문제

일반화 된 것을 작성할 수 있습니까? orElse 방법 Option 변수의 인수가 필요합니까? 즉, 대신 :

lazy val o1 = { println("foo"); None }
lazy val o2 = { println("bar"); Some("bar") }
lazy val o3 = { println("baz"); Some("baz") } 
// ...
o1 orElse o2 orElse o3 // orElse ...

당신은 사용할 수 있습니다 :

orElse(o1, o2, o3) //, ...
도움이 되었습니까?

해결책

에 따르면 스칼라 언어 사양 (4.6 기능 선언 및 정의) Varargs를 이름 별 매개 변수를 정의 할 수 없습니다.

ParamType ::= Type
| ‘=>’ Type
| Type ‘*’

scala> def orElse(x : (=> String)*)
<console>:1: error: no by-name parameter type allowed here
       def orElse(x : (=> String)*)

게으른 Arg를 기능 및 암시 적 유형 변환으로 바꿀 수 있습니다.

def orElse[T](x : (()=> Option[T])*) : Option[T] = 
    if(x.isEmpty) None else x.first.apply.orElse(orElse((x drop 1) :_*))
implicit def anyToFun0[T](t : => T) : (() => T) = () => t
orElse(o1, o2, o3)

다른 팁

나는 질문을 조금 늦게 찾았다 :). 한 가지 가능성은 포장하는 것입니다 => 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]

보다 효율적인 구현으로.


이미 비슷한 수업이 있습니다 Helper Scalaz에서 Name 구현과 함께 Need 신체가 최대 한 번에 평가되도록합니다. 따라서 Scalaz의 경우 AS를 구현할 수 있습니다

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) //, ...
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top