我对在Scala中使用逐名调用参数感到有点困惑。请帮我了解一下这里发生了什么。请考虑以下使用按名称调用参数的示例:
def param = {println("Param evaluates"); 40}
def lazyEval(x: => Int) = {
println("lazy");
x
}
val s = lazyEval(param + 2)
// s = 42关于这一点,我有几个相互关联的问题:
lazyEval方法需要=> Int类型的参数,那么为什么param + 2操作是合法的?为什么在调用=> Int方法时,我们可以将整数2添加到带有<function0>类型的对象(我的理解是<function0>)?正如IDE提示我的那样,lazyEval函数需要Int类型的参数,而不是=> Int (到底是什么?)。=> Int更改为() => Int代码后不编译?这两种不同吗?我认为简短的版本('=> Int')只是一个语法糖。() => Int编译了。这条路对我来说更直观。。
def param = {println("Param evaluates"); 40}
def lazyEval(x: () => Int) = { // changed type to '() => Int'
println("lazy");
x() // explicitly calling function using parentheses '()'
}
val s = lazyEval(param _) // adding underscore after method name and removing `+2`这个版本和第一个版本(使用回调=> Int类型)有什么不同?为什么在这个版本中我们不能用值2和param函数(我指的是这个lazyEval(param _ + 2))来加法整数呢?方法名称后面的下划线是什么意思?(我猜它以前是传递方法本身,而不是返回值)
感谢帮助
发布于 2015-03-22 02:40:18
那么为什么param +2操作是合法的呢?为什么我们可以将整数2添加到具有=> Int类型的对象中
我们可以将2添加到param中,因为它的计算结果是Int,您要用Int添加Int。param不是一个函数=> Int,它是一个方法,所以param + 2是=> Int。即。计算为Int的表达式。
为什么在将回调类型从=> Int更改为()之后,=> Intcode不编译?这两种不同吗?我认为简短的版本('=> Int')只是一个语法糖。
=> Int和() => Int的意思不一样。一种是计算为Int的任何东西,另一种是从Unit到Int的函数。2不是() => Int,但() => 2是。或者你也可以说2是=> Int。
为什么在这个版本中,我们不能用值2和param函数(我是指thislazyEval(param _+ 2))进行整数的加法?方法名称后面的下划线是什么意思?(我猜它以前是传递方法本身,而不是返回值)
param是一种方法,而不是函数。在这种情况下,下划线将param提升为一个函数。所以param _是一个函数() => Int。这就是为什么我们不能将2添加到其中,因为您不能将2添加到函数中。基本上,你认为(1)不应该起作用的确切原因。
总结如下:
def lazyEval(x: => Int)是一个具有参数x的方法,它可以是任何计算结果为Int的方法。这可能是任何返回Int、Int的具体值或解析为Int的代码块的方法,等等。
lazyEval(x: () => Int)是一个具有参数x的方法,该参数只能是返回Int的无参数函数。这可能意味着param提升到一个函数的方法,或者类似于() => 2之类的奇怪方法。但它一定是一种功能。因此,简单地传递一个像2这样的值就无法工作。
发布于 2015-03-22 04:30:20
正如@m-z所指出的,可以将value: => T视为创建包装给定表达式的方法的语法。
object Magician {
def magic(param: => Int) = param
}
object App {
val result: Int = Magician.magic(3 + 3)
}翻译(大致)为:
object App {
private[this] def magic$param$1: Int = 3 + 3
val result: Int = Magician.magic(magic$param$1 _)
}逐名调用参数的行为类似于无参数的方法定义-引用结果之一是调用方法:
def paramlessMethod = 3 + 3
def callByName(param: => Int) = param + paramlessMethod
def test() = callByName(5 + 5) // 16, always在这两种情况下,您都可以通过使用神奇的Function0将该方法“提升”到一个_ (或者“推迟方法的评估”,如果您愿意这样想的话)。
def paramlessMethod = 3 + 3
val functionWrapper: Function0[Int] = paramlessMethod _
functionWrapper() // 6
def callByName(param: => Int) = param _
val functionFromParam: Function0[Int] = callByName(3 + 3)
functionFromParam() // 6发布于 2015-03-22 08:12:50
这里解释了def i: Int的类型:
http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#method-types
这里解释了按名参数i: => Int的类型:
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#by-name-parameters
然后,这种参数的类型是无参数方法类型=> T。
换句话说,它与方法类型def i: Int相同。
https://stackoverflow.com/questions/29190253
复制相似问题