scala中的传名调用
Posted 后端技术小黑屋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala中的传名调用相关的知识,希望对你有一定的参考价值。
scala函数调用的参数传递有两种方式:
一种是传值调用,这种方式和C语言的函数参数传递方式类似,在函数调用的时刻,计算各个参数的值,然后传递进入函数内部,scala中写作function(x: Int);
一种是传名调用,这种调用方式在函数调用时并不直接计算参数的具体值,而是在函数中使用到该参数时,才进行计算,scala中写作function(x: =>Int)。这里有意思的地方在于,在scala中, Int => Int表示一个函数类型,接受Int参数,返回Int返回值。那这里x的类型,就类似于一个函数,它没有参数,但是返回一个Int类型的返回值。
下面看一个并没有什么卵用,只为用于说明特性的例子:
package example
object TestThunk extends Greeting with App {
def printAndReturnInt() = {
println("test...")
1
}
callByValue(printAndReturnInt)
callByName(printAndReturnInt)
}
trait Greeting {
def callByValue(x: Int) = {
println("first call by value: x=" + x)
println("second call by value: x=" + x)
}
def callByName(x: => Int) = {
println("first call by name: x=" + x)
println("second call by name: x=" + x)
}
}
调用结果输出是:
test...
first call by value: x=1
second call by value: x=1
test...
first call by name: x=1
test...
second call by name: x=1
通过test…的输出,可以看出传名调用和传值调用的区别。
那这个传名调用,有什么作用呢?
首先,在部分情况下它可以提高效率:比如函数中没有用到这个传名调用参数的时候,这个参数就不会被计算。
但是,既然不会用到这个参数,你传它进函数干嘛?其实也是有这种情况的,比如熟悉的getOrElse,它的默认取值default就是一个传名调用:
def getOrElse[B >: A](default: ⇒ B): B
另外,这种延迟参数计算到函数中实际调用位置的方式,也为scala的一些特性提供了支撑,比如Try:
Try的apply方法,接收的就是一个传名参数:
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
只有在构造Try时使用传名参数r,将r的调用推迟到Try内部,才能够在Try内部对异常进行处理;否则的话,r将在传入Try内部之前进行计算,在计算中出现的异常将会直接抛到Try外部,就不能实现Try对于异常的包装了,是不是很神奇很有用?
推荐阅读:
题图:GraphicMam-team
授权:CC0协议
以上是关于scala中的传名调用的主要内容,如果未能解决你的问题,请参考以下文章