Creo que puede beneficiarse del uso de Lift's Box, que tiene Full
(es decir, Some
), Empty
(es decir None
) y Failure
(un Empty
con un motivo por el que está vacío y que se puede encadenar). David Pollak tiene un good blog post que lo presenta. En resumen, es posible hacer algo como esto (no probado):
def validate1: Box[String]
def validate2: Box[String]
def validate3: Box[String]
val validation = for (
validation1 <- validate1 ?~ "error message 1"
validation2 <- validate2 ?~ "error message 2"
validation3 <- validate3 ?~ "error message 3"
) yield "overall success message"
Esto no es más corto que el ejemplo original, sino que es, en mi opinión, un poco más lógico, con el resultado de una validación exitosa en un Full
y una validación fallida en Failure
.
Sin embargo, podemos hacernos más pequeños. En primer lugar, ya que nuestra función de validación volver Box[String]
, pueden volver a sí mismos Failure
S y que no necesitan para transformar a Empty
Failure
nosotros mismos:
val validation = for (
validation1 <- validate1
validation2 <- validate2
validation3 <- validate3
) yield "overall success message"
Pero, Box
también tiene un método or
que devuelve el mismo Box
si es Full
o el otro Box
si no lo es. Esto nos daría:
val = validación validate1 o validate2 o validate3
Sin embargo, esa línea se detiene en el primer éxito de validación , no es el primer fallo. Puede tener sentido hacer otro método que haga lo que quiera (¿tal vez llamado unless
?) Aunque no puedo decir que realmente sería mucho más útil que el enfoque de comprensión.
Sin embargo, aquí hay un poco de proxenetismo biblioteca que lo hace:
scala> class Unless[T](a: Box[T]) {
| def unless(b: Box[T]) = {
| if (a.isEmpty) { a }
| else b
| }
| }
defined class Unless
scala> implicit def b2U[T](b: Box[T]): Unless[T] = new Unless(b)
b2U: [T](b: net.liftweb.common.Box[T])Unless[T]
scala> val a = Full("yes")
a: net.liftweb.common.Full[java.lang.String] = Full(yes)
scala> val b = Failure("no")
b: net.liftweb.common.Failure = Failure(no,Empty,Empty)
scala> val c = Full("yes2")
c: net.liftweb.common.Full[java.lang.String] = Full(yes2)
scala> a unless b
res1: net.liftweb.common.Box[java.lang.String] = Failure(no,Empty,Empty)
scala> a unless b unless c
res2: net.liftweb.common.Box[java.lang.String] = Failure(no,Empty,Empty)
scala> a unless c unless b
res3: net.liftweb.common.Box[java.lang.String] = Failure(no,Empty,Empty)
scala> a unless c
res4: net.liftweb.common.Box[java.lang.String] = Full(yes2)
Este es un truco rápido basado en mi limitada comprensión del sistema de tipos de Scala, como se puede ver en el siguiente error:
scala> b unless a
<console>:13: error: type mismatch;
found : net.liftweb.common.Full[java.lang.String]
required: net.liftweb.common.Box[T]
b unless a
^
Sin embargo, eso debería ser suficiente para llevarlo por el camino correcto.
Por supuesto, el Lift ScalaDocs tiene más información en Box.
La última línea podría simplificarse un poco: '(validate1 ++ ++ validate2 validate3) .head' – pr1001
No creo que quieren soltar las llamadas '.iterator' - entonces siempre llamará a todos los métodos de validación en lugar de llamar solo a los métodos hasta que uno de ellos devuelva un error. – Steve
Ahh, ya veo, muy inteligente. – pr1001