lambdas
lambdas

Reputation: 4060

Function literal with multiple implicit arguments

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

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

but it throws compilation error.

Upvotes: 10

Views: 1996

Answers (4)

Ceasar
Ceasar

Reputation: 23083

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.

Upvotes: 0

Chris Vandevelde
Chris Vandevelde

Reputation: 1441

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

Upvotes: 0

lambdas
lambdas

Reputation: 4060

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.

Upvotes: 18

pagoda_5b
pagoda_5b

Reputation: 7373

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}

Upvotes: 6

Related Questions