Need plain english translation of the following scala snippet

后端 未结 1 1896
耶瑟儿~
耶瑟儿~ 2021-02-13 21:57

I\'m new to scala and the playframework. Can somebody please translate the following snippet below into plain english? For context its found here: http://www.playframework.org

相关标签:
1条回答
  • 2021-02-13 22:25

    Part 1: First let's address the curried syntax:

    withUser is a method that takes a curried function f of type User => Request[AnyContent] => Result. It takes a User object and returns another function that takes a Request and returns a Result. Breaking it down, if f is that function then:

    val g = f(user) // g is a function
    val result = g(request) // returns a result
    // same as:
    val result = f(user)(request)
    

    Practically speaking f is just like a function that takes two parameters but instead of calling f(a, b) you call f(a)(b).

    withAuth is also a method that takes a curried function. It has almost the same type as withUser.

    Part 2: Now how do you use those methods:

    As explained here, play makes you defined your application logic by telling it how to transform Request objects into Result objects.

    withAuth is a helper function that takes care of the authentication for you and conveniently retrieves the username. So you use it like this:

    def index = withAuth { username => implicit request =>
      Ok(html.index(username))
    }
    

    It returns a function that takes a Request and returns a Result, which is what play needs. But what it takes is a curried function (that takes a username) and return a function (that takes a request). The request parameter is marked as implicit so it can be passed implicitly to any function/method call that needs an implicit request parameter. For the purpose of this explanation, just ignore the implicit keyword.

    Part 3: Translation of withUser

    Well, its signature is similar to withAuth and the goal is for it to be used in the same way except the first parameter will be a User instead of a String. So it has to take a User => Request => Result. The request trait takes a type parameter which indicates the type of its content. Here it is AnyContent. So the correct type for the argument of withUser is User => Request[AnyContent] => Result. That means you will be able to use it like this:

    withUser { user => implicit request =>
      // do something with user and request to return a result
    }
    

    If you look at the definition of withUser, all it does is to call withAuth:

    def withUser(f: User => Request[AnyContent] => Result) = withAuth { 
      // ...
    }
    

    So it will return the same type as withAuth which means it will return a function that turns a Request into a Result (see Part 2 above). Which means we will be able to use it like this:

    def index = withUser { user => implicit request => 
      Ok(html.index(user))
    }
    

    What is passed as an argument of withAuth is a curried function. I introduced intermediate val so that you can follow the types:

    username => // first param is the username as a String
      implicit request => // second param is the request
        // here we have to return a Result...
        // we lookup the user - we may not have one:
        val userOption: Option[User] = UserDAO.findOneByUsername(username)
        // f is the code block that will be provided inside withUser { f }
        // Part 1 explains the f(user)(request) syntax
        // We call f to get a result, in the context of the Option monad
        val resultOption: Option[Result] = userOption.map(user => f(user)(request))
        // if we have a result, return it; otherwise return an error.
        resultOption.getOrElse(onUnauthorized(request))
    
    0 讨论(0)
提交回复
热议问题