I understand that a method can have code like this:
def m(p1:Int => Int) ...
Which means this method takes a function p1 that returns an Int
But while browsing the Play! framework code i found a trait with indecipherable methods:
trait Secured {
def username(request: RequestHeader) = request.session.get(Security.username)
def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Auth.login)
def withAuth(f: => String => Request[AnyContent] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
/**
* This method shows how you could wrap the withAuth method to also fetch your user
* You will need to implement UserDAO.findOneByUsername
*/
def withUser(f: User => Request[AnyContent] => Result) = withAuth { username => implicit request =>
UserDAO.findOneByUsername(username).map { user =>
f(user)(request)
}.getOrElse(onUnauthorized(request))
}
}
Play! Scala Security
What does the f: User => Request[AnyContent] => Result
mean? At first glance it looks like a method that returns a function r
of type Request; r
then returns a Result
.
Is this the right assumption?
The arrow functions are 3 levels nesting. It takes effort and time to understand what the code does. To increase readability of nested functions, the first approach is to introduce variables that each holds an arrow function.
An easy way to grasp this is to remember that a curried/double arrow function is a function that implicitly returns another function(s). Going by this logic, you could also have triple arrow functions and so on.
What does the f: User => Request[AnyContent] => Result mean? At first glance it looks like a method that returns a function r of type Request; r then returns a Result.
f
returns a function of type Request[AnyContent] => Result
, i.e. a function that takes a Request[AnyContent]
and returns a Result
.
In other words f
is a curried function. You could call it as f(user)(request)
to get back a Result
.
def withAuth(f: => String => Request[AnyContent] => Result)
means, that f
is a by-name parameter, and you can write something like this:
withAuth {
logger.info("Here we go")
...
chooseTheAction("list")
}
where chooseTheAction
takes a String
and returns a function performing a request, Request[AnyContent] => Result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With