浅析scala传名调用和传值调用,: => 与() : =>
来源:互联网 发布:底层软件开发工程师 编辑:程序博客网 时间:2024/06/07 06:59
函数调用一般传值调用,但是,在某些情况下,我们不希望函数的值首先被计算,而是等到调用的时候再来进行计算,为了适应这种情景,scala提供了传名调用。先来看两个例子:
package test/** * Created by layne on 05/05/17. */object Test { def byValue(code: () => Unit): Unit = { println("start") code() //1 println("end") } def byName(code: => Unit): Unit = { println("start") code println("end") } def main(args: Array[String]): Unit = { byValue { //2 println("calculated") () => println("test1") } println("------------------------") byName { println("uncalculated") println("test2") } }}
- 注释1:这里必须用code(),这里函数值经过scala解释器翻译成了一个Function0的实例对象,而code存了这个对象的引用,实际上是code.apply()方法的调用
注释2:这里函数值将先被计算,计算结果恰好是一个签名为 () => Unit 的匿名函数,如果计算结果为其他形式的话,这里将不能编译
执行结果为:
calculatedstarttest1end------------------------startuncalculatedtest2end
这里我们明显看出来byValue中代码在传入前就被计算了,而byName中的是在调用时才进行计算。
再来一个例子:
package layne.blog.byName/** * Created by layne on 08/05/17. */object MyAssert { def nameAssert(predicate: => Boolean, enableAssert: Boolean): Unit = { if (enableAssert && !predicate) throw new Error("断言错误") } def valueAssert(predicate: Boolean, enableAssert: Boolean): Unit = { if (!enableAssert && predicate) throw new Error("断言错误") } def main(args: Array[String]): Unit = { //禁止断言 //1 nameAssert(1 / 0 > 0, false) //禁止断言的情况下,传名调用不会报错,因为predicate没有被计算 //2 //valueAssert(1/0 > 0,false) //允许断言 //3 //nameAssert(1/0 >0 ,true) }}
依次执行上述函数结果
1:没有任何输出2:Exception in thread "main" java.lang.ArithmeticException: / by zero at layne.blog.byName.MyAssert$.main(MyAssert.scala:19) at layne.blog.byName.MyAssert.main(MyAssert.scala)3:Exception in thread "main" java.lang.ArithmeticException: / by zero at layne.blog.byName.MyAssert$$anonfun$main$1.apply$mcZ$sp(MyAssert.scala:21) at layne.blog.byName.MyAssert$.nameAssert(MyAssert.scala:9) at layne.blog.byName.MyAssert$.main(MyAssert.scala:21) at layne.blog.byName.MyAssert.main(MyAssert.scala) 2和3虽然都报了异常,但是请注意异常信息的层级,同样印证了nameAssert是在调用时进行计算的
最后来一个实际有用的例子:
package layne.blog.byName/** * Created by layne on 08/05/17. */object TestUntil { /** * 与while作用相反 * @param condition * @param block */ def until(condition: => Boolean)(block: => Unit): Unit = { //执行 if (!condition) { block //传名调用 until(condition)(block) } } def main(args: Array[String]): Unit = { var i = 0 //这里利用柯里化和单参数调用能将()改成{},写出形如内置关键字的代码 until(i > 4) {//直到i>4就停下来 println(i) i += 1 } }}
最近在自学scala,顺便尝试写写博客。希望给同样在学的童鞋们一点帮助,也希望各位老鸟给点指导!
1 0
- 浅析scala传名调用和传值调用,: => 与() : =>
- scala传值调用和传名调用
- Scala函数传名调用
- scala 传值参数和传名参数 ():=>和:=>
- Scala从零开始:函数参数的传名调用(call-by-name)和传值调用(call-by-value)
- scala 传名调用call-by-name
- Scala 函数传名调用(call-by-name)
- Scala基础应用(10)- 传值与传名参数
- scala的传名参数和传值参数
- scala的传值参数和传名参数
- Scala 学习笔记(一)------函数传名调用(call-by-name)
- Scala 按名称参数调用函数 与 =>的用法
- iOS 传名称,调用地图客户端查询位置
- scala调用matlab方法传参和接收返回数据
- Scala和Java方法的相互调用
- 传值调用与传值调用
- 传值调用与传址调用
- 传引用调用与传值调用
- UUID与获取随机验证码
- HDU5510 Bazinga
- 查找linux进程所在的目录
- This version of Android Studio is incompatible with the Gradle Plugin used.
- spring+mybatis缓存的问题及源码
- 浅析scala传名调用和传值调用,: => 与() : =>
- 获取Android设备电池电量状态
- mahout之聚类实现
- oracle优化
- 清除行列
- 解决Could not read from remote repository问题,为GitHub账号添加SSH Keys。图片案例
- [求助]关于java的心跳包程序出现java.net.SocketException: Software caused connection abort: socket write error
- OpenGL编程指南14:混合半透明Blend
- kafka的相关组件介绍