Implícito dentro de la coincidencia de patrones
-
10-12-2019 - |
Pregunta
Tengo un método que tiene muchos parámetros implícitos:
def hello(message:String)(implicit a:A,b:B,c:C, ..., user: User) = {...}
Ahora considere 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
}
}
}
Puede ver esta línea en el ejemplo anterior:
implicit val _user = user
Existe sólo para hacer el objeto. user
como un objeto implícito.De lo contrario, tengo que llamar hello
como:
hello("implicit")(a,b,c,... user)
Estoy pensando si hay alguna forma de mejorar el código, por ejemplo.no necesitamos definir eso _user
variable pero hacer el user
está implícito.
Solución
Sí, hay una manera de eliminar. _user
variable mientras se hace user
implícito:
def index(id:String) = Action {
User.findById(id) map (implicit user => hello("implicit")) getOrElse BadRequest
}
ACTUALIZAR: Respondiendo su pregunta sobre muchos casos en los comentarios a continuación.
Todo depende del tipo de valor que devuelva User.findById
.Si es Option[User]
pero desea hacer coincidir usuarios específicos (asumiendo User
es una clase de caso), entonces la solución original aún se aplica:
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 puedes combinar cualquier otra cosa si quieres, siempre y cuando User.findById
es String => Option[User]
Si, por el contrario, User.findById
es String => User
entonces simplemente puedes definir un objeto auxiliar como:
object withUser {
def apply[A](user: User)(block: User => A) = block(user)
}
Y utilícelo de la siguiente manera (nuevamente asumiendo 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 hacer coincidir algún otro valor, digamos un 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 cubra todos los escenarios que pueda tener.
Otros consejos
No conozco ningún truco como el caso Some(implicit user)
pero que 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)