Skip to content

Instantly share code, notes, and snippets.

@jducoeur
Created January 27, 2014 14:26
Show Gist options
  • Save jducoeur/8649435 to your computer and use it in GitHub Desktop.
Save jducoeur/8649435 to your computer and use it in GitHub Desktop.
private[ql] case class InvocationValueImpl[T](inv:Invocation, vs:Iterable[T], errOpt:Option[PublicException] = None)(implicit val ecology:Ecology)
extends InvocationValue[T] with EcologyMember
{
lazy val QL = interface[QL]
def map[R](f:T => R):InvocationValue[R] = {
errOpt match {
// If there has already been an error, just propagate that:
case Some(err) => InvocationValueImpl[R](inv, None, errOpt)
// Otherwise, actually call f:
case None => {
val maps = vs.map(v => f(v))
InvocationValueImpl(inv, maps, None)
}
}
}
def flatMap[R](f:T => InvocationValue[R]):InvocationValue[R] = {
errOpt match {
// If there has already been an error, just propagate that:
case Some(err) => InvocationValueImpl[R](inv, None, errOpt)
// Otherwise, actually call f:
case None => {
// This gets a little complex, so that we can preserve interim errors:
(InvocationValueImpl(inv, Seq.empty[R], None) /: vs) { (current, v) =>
current.errOpt match {
case Some(err) => InvocationValueImpl[R](inv, None, current.errOpt)
case None => {
// HACK: is there a really good way of avoiding this cheat without polluting the public API of
// InvocationValue with the errOpt?
val result = f(v).asInstanceOf[InvocationValueImpl[R]]
result.errOpt match {
case Some(err) => result
case None => InvocationValueImpl(inv, current.vs ++: result.vs, None)
}
}
}
}
}
}
}
def get:Iterable[T] = vs
def getError:Option[QValue] = errOpt.map { ex =>
val msg = ex.display(Some(inv.context.request))
QL.WarningValue(msg)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment