Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Code demystify

Could someone demystify this code which is part of the zentasks example in the Play20 framework. I'm curious how this works, granted I'm new to Scala from Java so a lot of things are tough to wrap my head around.

def IsAuthenticated(f: => String => Request[AnyContent] => Result) = 
  Security.Authenticated(username, onUnauthorized) { user =>
    Action(request => f(user)(request))
  }
like image 626
chiappone Avatar asked Dec 21 '11 22:12

chiappone


2 Answers

You need to split up the signature a bit. f is a function that takes a not-yet-computed string => String and returns another function that accepts a Request[AnyContent] and returns a result.

The Security.Authenticated call accepts two parameters lists. One that has username and onUnauthorized. The second takes a function accepting the user and returning an action.

The Action.apply method accepts a function Request[AnyContent] => Result

so, the f is called in 'curried' fashion. That is the first function is called, and then the resulting function is immediately used f(user)(request).

Here's the same thing desugared (at least, as best I can) and ugly:

def isAuthenticated(f: => String => Request[AnyContent] => Result) =
  Security.Authenticated(username, onUnauthorized) { user: String =>
     Action.apply { request: Request[AnyContent] =>
       val hiddenTmp: Request[AnyContent] => Result = f(user)
       hiddenTemp.apply(request)
     }
  }

You can see the compiler is doing a bit of work removing type annotations. Hopefully that helps explain how it desugars into raw scala. Essentially, the function does a lot of functional composition.

like image 63
jsuereth Avatar answered Oct 02 '22 23:10

jsuereth


First off a user guide to my answer: I will use italics to indicate a function that is used without being explicitly named (see anonymous functions).

IsAuthenticated is a method which takes as a parameter an argument f.

f is a function which takes Y as a parameter and produces an instance of Result

Y is a function which takes Z as a parameter and produces an instance of Request[AnyContent]

Z is a function which takes no parameters and returns a String

IsAuthenticated calls Security.Authenticated, passing username and onUnauthorized (a function to call when the user is not authorized to perform the requested action).

I am not entirely sure what's going on past here myself- I'm not quite that good with Scala yet- but my guess is that Security.Authenticated is a case class, and the following is equivalent to subclassing it and adding a constructor in java:

{
  Action(request => f(user)(request))
}

If that much of my assumption is correct, then Action (which is a method on Security.Authenticated) is being called, passing as an argument a A.

A is a function which takes a Request object (I am guessing at this class name) and produces a Result. The use of Result is implied here because the implementation of A is a call to f.

So when the subclass of Security.Authenticated is instanciated, Action is called, which authenticates the user for some action (specified as a String) and then if the user is authenticated, returns f (the original parameter) which is presumably called by Action (after the aforementioned authentication). This call to f returns a Result, which is also a function. Result is then finally called with request (which was passed to A) as a parameter.

like image 27
Chris Shain Avatar answered Oct 02 '22 23:10

Chris Shain