【问题标题】:Implicit within pattern match模式匹配中的隐式
【发布时间】:2012-03-09 11:30:15
【问题描述】:

我有一个方法,有很多隐式参数:

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 是隐式的。

【问题讨论】:

    标签: scala playframework-2.0 pattern-matching implicit


    【解决方案1】:

    是的,有一种方法可以消除 _user 变量同时使 user 隐含:

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

    更新:解决您关于以下 cmets 中许多案例的问题。

    这完全取决于User.findById 返回的值类型。如果是 Option[User] 但您想匹配特定用户(假设 User 是一个案例类),那么原始解决方案仍然适用:

    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.findByIdString => Option[User]

    另一方面,如果User.findByIdString => User,那么您可以简单地定义一个辅助对象,例如:

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

    并按如下方式使用它(再次假设User 是一个案例类):

    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
        }
      }
    }
    

    我希望这涵盖了您可能遇到的所有情况。

    【讨论】:

    • +1,如果模式匹配Option,这是一个很好的解决方案。但是如果cases 有很多呢?
    【解决方案2】:

    我不知道 case 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)
    

    【讨论】:

    • 谢谢。我觉得hello(message)(implicit ...)应该是已有的,不能更改,否则我们不需要定义它,只要定义一个hello(message,user)(implicit ...) on就够了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2021-02-05
    • 2022-01-11
    • 1970-01-01
    • 2011-02-03
    • 2011-07-15
    相关资源
    最近更新 更多