从Play framework任务示例了解Scala函数
这是Application.scala中zentask示例中的一个函数。 我正在努力理解它 f:=>字符串是什么意思 那么f:=>String=>Request[AnyContent]=>Result的链接呢从Play framework任务示例了解Scala函数,scala,playframework-2.0,Scala,Playframework 2.0,这是Application.scala中zentask示例中的一个函数。 我正在努力理解它 f:=>字符串是什么意思 那么f:=>String=>Request[AnyContent]=>Result的链接呢 /** * Action for authenticated users. */ def IsAuthenticated(f: => String => Request[AnyContent] => Result) = Security.Authen
/**
* Action for authenticated users.
*/
def IsAuthenticated(f: => String => Request[AnyContent] => Result) =
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
格式为
fn:=>String
的参数表示返回(或是)字符串的“生成器”(函数或值),因此,例如,您可以将方法定义为
def myMethod(fn: => String): String = "Fn output = " + fn
如下调用(我在这里使用的返回类型通常可以由编译器推断,我只是出于教学目的添加它们):
在此基础上,我们可以定义一个方法,该方法采用将字符串转换为Int的函数,例如:
def my2ndMethod(fn: String => Int): Int = fn("4")
并称之为:
def my2ndFn(input: String) = 5 * input.toInt
// Alternatively: val my2ndFn: String => Int = input => 5 * input.toInt
val output2 = my2ndMethod(my2ndFn _) // output2 = 20
def authFn(username: String)(request: Request[AnyContent]): Result
val authenticatedResult = IsAuthenticated(authFn _)
在您提供的例子中,您有一个更复杂的实体:它返回(或是)一个接受字符串的函数,并返回另一个函数,该函数依次接受请求[AnyContent]
,并(最终)返回一个结果(phew!)
您还可以将其视为采用定义和使用如下的函数:
def my2ndFn(input: String) = 5 * input.toInt
// Alternatively: val my2ndFn: String => Int = input => 5 * input.toInt
val output2 = my2ndMethod(my2ndFn _) // output2 = 20
def authFn(username: String)(request: Request[AnyContent]): Result
val authenticatedResult = IsAuthenticated(authFn _)
实际上,要弄清楚操作员是如何关联的有点棘手:
f: => String => Request[AnyContent] => Result
与
f: (=> String) => (Request[AnyContent] => Result)
因此,f
是一个函数,它接受一个=>字符串
,并返回一个函数,该函数接受一个请求并返回一个结果。正如我在评论中所指出的那样,请看一看对发生的一些事情的解释
那么,为什么将=>String
作为第一个参数而不是String
?我的猜测是,如果您希望用户通过名称传递具有第一个参数的函数(意味着每次需要时都会对其求值),那么它就起作用了
假设你有一个方法g
:
def g(s: => String): String => String = arg => s + arg
如果要编写一个方法m
,该方法将方法g
作为参数,则需要这样编写:
def m(f: (=> String) => (String => String)) = f("a")("b")
m(g) // compiles
def n(f: String => (String => String)) = f("a")("b")
n(g) // does not compile
// found : => String => (String => String)
// required: String => (String => String)
如果你这样写:
def m(f: (=> String) => (String => String)) = f("a")("b")
m(g) // compiles
def n(f: String => (String => String)) = f("a")("b")
n(g) // does not compile
// found : => String => (String => String)
// required: String => (String => String)
请看另一个问题/答案,看看您的问题/答案是否重复:。我花了相当长的时间解释了一个类似的例子。谢谢你澄清了“按姓名传递”的惯例。还有一个问题:在my2ndMethod(my2ndFn_)中下划线的用途是什么?@seand-有关下划线的用途,请参阅我对的回答。本质上,它告诉编译器将函数作为参数传递,而不是计算结果。