Scala代码剖析

10

有人能够解释一下这段代码吗?它是Play20框架中zentasks示例的一部分。我很好奇它是如何工作的,尽管我是从Java转到Scala的新手,所以很多东西都很难理解。

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

有没有办法用Java语法来表示这个?我知道它们不完全一样,但可以帮助我理解方法签名。我在这里的操作顺序方面遇到了困难。 - chiappone
2个回答

16

你需要将签名拆开。 f 是一个函数,它接受一个尚未计算的字符串 => String 并返回另一个函数,该函数接受一个 Request[AnyContent] 并返回结果。

Security.Authenticated 调用接受两个参数列表。第一个包含 usernameonUnauthorized。第二个接受一个接受用户并返回动作的函数。

Action.apply 方法接受一个函数 Request[AnyContent] => Result

因此,f 以“柯里化”的方式调用。即首先调用第一个函数,然后立即使用生成的函数 f(user)(request)

这里是同样的事情被展开(至少,我尽力了)并且难看的:

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

你可以看到编译器正在工作中,消除类型注释。希望这有助于解释它是如何转化为原始Scala代码的。本质上,该函数进行了大量的函数组合。


2
首先,我会使用斜体表示未显式命名的函数(请参见匿名函数)。
IsAuthenticated是一个方法,它以参数f作为参数。
f是一个函数,它以Y作为参数并生成Result的实例。 Y是一个函数,它以Z作为参数并生成Request 的实例。 Z是一个函数,它不带参数并返回一个字符串。
IsAuthenticated调用Security.Authenticated,传递用户名和onUnauthorized(当用户未被授权执行所请求的操作时要调用的函数)。 在这之后我并不完全确定发生了什么-我还不太擅长Scala-但我的猜测是Security.Authenticated是一个case类,并且以下内容等同于在Java中添加构造函数的子类化:
{
  Action(request => f(user)(request))
}

如果我所假设的大部分正确,那么Action(Security.Authenticated上的一种方法)会被调用,并将A作为参数传入。 A是一个函数,它接受一个Request对象(我猜测这个类名),并生成一个Result。在这里,Result的使用是暗示的,因为A的实现是对f的调用。
因此,当Security.Authenticated的子类被实例化时,会调用Action,该操作对某些动作(以字符串形式指定)对用户进行身份验证,然后如果用户已通过身份验证,则返回f(原始参数)。这个调用f返回一个Result,也是一个函数。最后,Result被以request(传递给A)作为参数调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接