Function literal with multiple implicit arguments

后端 未结 4 967
南笙
南笙 2020-12-20 15:43

How to define function literal with multiple implicit arguments in Scala? I\'ve tried this way:

def create = authAction { (implicit request, user) ⇒ // Synta         


        
相关标签:
4条回答
  • 2020-12-20 15:57

    Just had a similar situation as you, implementing an authAction function in Play that would easily pass a user in. You can do it like lambdas did it, with currying; I ended up making my authAction function receive the RequestHeader implicitly, but pass in both request and user explicitly:

    def authAction(f: (RequestHeader, User) => Result)(implicit request: RequestHeader) = {
        ...
        val authUser = loadUser(...)
        f(request, authUser)
    }
    

    And to use it:

    def create = authAction { (request, user) =>
        Ok(html.user.create(registrationForm))
    }
    
    0 讨论(0)
  • 2020-12-20 16:07

    As stated in previous answer, you can only define a single implicit parameter for a function literal, but there is workaround.

    Instead of multiple implicit arguments you can write function literal as taking multiple argument lists with one argument each. Then it is possible to mark each argument as implicit. Rewriting original snippet:

    def create = authAction { implicit request ⇒ implicit user ⇒
      Ok(html.user.create(registrationForm))
    }
    

    You can call it from authAction as f(request)(user).

    implicit keyword duplication is annoying, but at least it works.

    0 讨论(0)
  • 2020-12-20 16:20

    There is no way to define an anonymous function with multiple implicit parameters.

    To elaborate on @pagoda_5b's answer and @paradigmatic's comment, section 6.23 of the Scala Language Specification defines anonymous functions like so:

    Expr ::= (Bindings | [‘implicit’] id | ‘_’) ‘=>’ Expr
    ResultExpr ::= (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block
    Bindings ::= ‘(’ Binding {‘,’ Binding} ‘)’
    Binding ::= (id | ‘_’) [‘:’ Type]
    

    As you can see, you can either define a list of parameters or a single implicit parameter.

    If you need multiple parameters to be implicit, you need to curry them.

    0 讨论(0)
  • 2020-12-20 16:22

    From what I can understand of the language specification, as of version 2.9.2 you can only define a single implicit parameter for anonymous functions.

    E.g.

    val autoappend = {implicit text:String => text ++ text}
    
    0 讨论(0)
提交回复
热议问题