Неявное соответствие шаблону
-
10-12-2019 - |
Вопрос
У меня есть метод, имеющий множество неявных параметров:
def hello(message:String)(implicit a:A,b:B,c:C, ..., user: User) = {...}
Теперь рассмотрим такой класс:
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
}
}
}
Вы можете увидеть эту строку в приведенном выше примере:
implicit val _user = user
Он существует только для того, чтобы создать объект user
как неявный объект.В противном случае мне придется позвонить hello
как:
hello("implicit")(a,b,c,... user)
Я думаю, есть ли какой-нибудь способ улучшить код, напримернам не нужно это определять _user
переменной , но сделать так, чтобы user
является неявным.
Решение
Да, есть способ устранить _user
переменная при создании user
неявный:
def index(id:String) = Action {
User.findById(id) map (implicit user => hello("implicit")) getOrElse BadRequest
}
ОБНОВЛЕНИЕ: Отвечая на ваш вопрос о многих случаях в комментариях ниже.
Все зависит от того, какой тип значения возвращается User.findById
.Если это Option[User]
но вы хотите соответствовать конкретным пользователям (предполагая User
является классом case), то исходное решение по-прежнему применяется:
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
Или вы можете подобрать что-нибудь еще, если хотите, при условии, что User.findById
является String => Option[User]
Если, с другой стороны,, User.findById
является String => User
затем вы можете просто определить вспомогательный объект типа:
object withUser {
def apply[A](user: User)(block: User => A) = block(user)
}
И используйте его следующим образом (опять же, предполагая User
является классом case):
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
}
}
}
или сопоставление с каким-либо другим значением, скажем, с 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
}
}
}
Я надеюсь, что это охватывает все возможные сценарии, которые у вас могут возникнуть.
Другие советы
Я не знаю такого трюка, как кейс Some(implicit user)
но как насчет
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)