2012-03-09 14 views
7

tengo un método, con una gran cantidad de parámetros implícitos:implícito dentro de coincidencia de patrones

def hello(message:String)(implicit a:A,b:B,c:C, ..., user: User) = {...} 

Consideremos ahora una clase así:

object Users extends Controller { 
    implicit a: A = ... 
    implicit b: B = ... 
    ... 

    def index(id:String) = Action { 
    User.findById(id) match { 
     case Some(user) => { 
      implicit val _user = user 
      hello("implicit") 
     } 
     case _ => BadRequest 
    } 
    } 
} 

Se puede ver esta línea en el ejemplo anterior:

implicit val _user = user 

existe sólo para hacer que el objeto user como un objeto implícito. De lo contrario, tengo que llamar a hello como:

hello("implicit")(a,b,c,... user) 

Estoy pensando que si hay alguna manera de mejorar el código, por ejemplo, no necesitamos definir esa variable _user, pero hacer que el user esté implícito.

Respuesta

5

Sí, hay una manera de eliminar _user variable de tiempo que user implícita:

def index(id:String) = Action { 
    User.findById(id) map (implicit user => hello("implicit")) getOrElse BadRequest 
} 

ACTUALIZACIÓN: Dirigiéndose su pregunta sobre muchos casos en los comentarios a continuación.

Todo depende de qué tipo de valor devuelve User.findById. Si se trata de Option[User] pero que desea hacer coincidir en usuarios específicos (suponiendo User es una clase de caso), entonces la solución original sigue siendo válida:

def index(id:String) = Action { 
    User.findById(id) map { implicit user => 
    user match { 
     case User("bob") => hello("Bob") 
     case User("alice") => hello("Alice") 
     case User("john") => hello("John") 
     case _ => hello("Other user") 
    } 
    } getOrElse BadRequest 

O usted puede igualar en cualquier otra cosa si lo desea, siempre y cuando User.findById es String => Option[User]

Si, por el contrario, es User.findByIdString => User, entonces puede simplemente definir un objeto de ayuda como:

object withUser { 
    def apply[A](user: User)(block: User => A) = block(user) 
} 

y utilizarlo como fo llows (suponiendo de nuevo User es una clase de caso):

def index(id: String) = Action { 
    withUser(User findById id) { implicit user => 
    user match { 
     case User("bob") => hello("Bob") 
     case User("alice") => hello("Alice") 
     case User("john") => hello("John") 
     case _ => BadRequest 
    } 
    } 
} 

o coincidente en algún otro valor, dicen una Int:

def index(id: String, level: Int) = Action { 
    withUser(User findById id) { implicit user => 
    level match { 
     case 1 => hello("Number One") 
     case 2 => hello("Number Two") 
     case 3 => hello("Number Three") 
     case _ => BadRequest 
    } 
    } 
} 

espero que esto cubre todos los escenarios que pueda tener.

+0

+1, es una buena solución si el patrón coincide con una 'Opción'. Pero, ¿y si hay muchos 'casos'? – Freewind

+0

@Freewind. He actualizado mi respuesta para cubrir muchos 'casos'. – romusz

2

No conozco ningún truco, como la carcasa Some(implicit user) pero ¿qué pasa

def hello(message: String, user: User)(implicit a: A, ... z: Z) = ... 
def hello(message: String)(implicit a: A, ... z: Z, user: User) = hello(message, user) 

case Some(user) => hello("implicit", user) 
+0

Gracias. Creo que 'hello (mensaje) (implícito ...)' debería ser el existente y no se puede cambiar, de lo contrario no necesitamos definirlo, solo definir un 'hello (mensaje, usuario) (implícito). .) 'on es suficiente. – Freewind

Cuestiones relacionadas