Implícito na correspondência de padrões
-
10-12-2019 - |
Pergunta
Eu tenho um método com muitos parâmetros implícitos:
def hello(message:String)(implicit a:A,b:B,c:C, ..., user: User) = {...}
Agora considere tal classe:
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
}
}
}
Você pode ver esta linha no exemplo acima:
implicit val _user = user
Ele existe apenas para tornar o objeto user
como um objeto implícito.Caso contrário, tenho que ligar hello
como:
hello("implicit")(a,b,c,... user)
Estou pensando se existe alguma maneira de melhorar o código, por ex.não precisamos definir isso _user
variável, mas faça o user
está implícito.
Solução
Sim, existe uma maneira de eliminar _user
variável ao fazer user
implícito:
def index(id:String) = Action {
User.findById(id) map (implicit user => hello("implicit")) getOrElse BadRequest
}
ATUALIZAR: Respondendo à sua pergunta sobre muitos casos nos comentários abaixo.
Tudo depende do tipo de valor retornado por User.findById
.Se é Option[User]
mas você deseja corresponder usuários específicos (assumindo User
é uma classe de caso), então a solução original ainda 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
Ou você pode combinar com qualquer outra coisa se quiser, contanto que User.findById
é String => Option[User]
Se, por outro lado, User.findById
é String => User
então você pode simplesmente definir um objeto auxiliar como:
object withUser {
def apply[A](user: User)(block: User => A) = block(user)
}
E use-o da seguinte maneira (novamente assumindo User
é uma classe 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
}
}
}
ou combinando algum outro valor, digamos um 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 isso cubra todos os cenários que você possa ter.
Outras dicas
Não conheço nenhum truque como o caso Some(implicit user)
mas e quanto
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)