Scala的解释器在解析函数参数(function arguments)时有两种方式:先计算参数表达式的值(reduce the arguments),再应用到函数内部;或者是将未计算的参数表达式直接应用到函数内部。前者叫做传值调用(call-by-value),后者叫做传名调用(call-by-name)。

传值函数和传名函数

object Add {
def addByName(a: Int, b: => Int) = a + b
def addByValue(a: Int, b: Int) = a + b
}

传名函数和传值函数在编译器中区别:

  addByName(,  + )
-> + ( + )
-> +
-> addByValue(, + )
->addByValue(, )
-> +
->

可以看出,在进入函数内部前,传值调用方式就已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。

这就造成了一种现象,每次使用传名调用时,解释器都会计算一次表达式的值。对于有副作用(side-effect)的参数来说,这无疑造成了两种调用方式结果的不同。

因此, 在实际的使用中:

传值调用在进入函数体之前就对参数表达式进行了计算,这避免了函数内部多次使用参数时重复计算其值,在一定程度上提高了效率。

但是传名调用的一个优势在于,如果参数在函数体内部没有被使用到,那么它就不用计算参数表达式的值了。在这种情况下,传名调用的效率会高一点。

package com.doggie  

object WhyAlwaysMe {
var flag: Boolean = true
def useOrNotUse(x: Int, y: => Int) = {
flag match{
case true => x
case false => x + y
}
}
def main(args: Array[String]) =
{
println(useOrNotUse(, ))
flag = false
println(useOrNotUse(, ))

=> Unit 与 () =>Unit的区别

简单来说, => Unit是 传名函数, 只传入了一个表达式, 在调用时才会去执行, 使用 code调用

() => 是传值函数, 传入的计算后的值, 使用 code() 调用

package main.scala

/**
* Created by wenbronk on 2017/9/12.
*/
object TestScala { def main(args: Array[String]): Unit = {
// println( addInt(3, 5))
// println(time())
delayTime({
println("");
time()
})
delayTime2({
println("");
time
})
} def delayTime2(t: () => Long): Unit = {
println("执行...")
println( t() )
println("jiesu..")
} def delayTime(t: => Long): Unit = {
println("执行开始")
println(t)
println("执行结束")
} def time() = {
println("获取时间内, 单位为 纳秒")
System.nanoTime()
} }

执行结果:

http://blog.csdn.net/asongoficeandfire/article/details/21889375

http://www.aboutyun.com/thread-10864-1-3.html

http://scalagroup.group.iteye.com/group/topic/26303

scala-传名函数和传值函数的更多相关文章

  1. Scala传名参数(By-Name)

    1.=> 在了解Scala的By-Name参数之前,先了解下“=>”在Scala中有几种用法: 1.对于值,“=>”相当于lambda表达式.如: scala> List(,, ...

  2. scala -- 传名参数

    object Test{ def main(args: Array[String]): Unit = { def test(code : => Unit){// 传名参数 不计算函数值,而是把函 ...

  3. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  4. 【Go入门教程5】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  5. C#-函数的传值与传址

    传值就是将实参的值传到所调用的函数里面,实参的值并没有发生变化,默认传值的有int型,浮点型,bool型,char字符型,结构体等等. 传址就是将地址传到所调用的函数里面操作,实参的值也会跟着变化,传 ...

  6. C# 函数的传值与传址(转)

    http://www.cnblogs.com/mdnx/archive/2012/09/04/2671060.html using System; using System.Collections.G ...

  7. scala的传名参数

    scala如果你想实现像if ,while等类似的控制结构,根本没有值要传入花括号{}直接的代码里.要怎么实现. 比如说,我们要实现一个断言的控制结构,myAssert(), myAssert函数参考 ...

  8. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数

    Python第七天   函数  函数参数   函数里的变量   函数返回值  多类型传值     函数递归调用   匿名函数   内置函数 目录 Pycharm使用技巧(转载) Python第一天   ...

  9. python基础----函数的定义和调用、return语句、变量作用域、传参、函数嵌套、函数对象、闭包、递归函数

    1.函数的定义: 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可 ...

随机推荐

  1. Memory Allocation Error

    Memory allocation error happened when I tried to install MySQL 5.7.13 in my server, which has 2G mem ...

  2. kepware http接口 java语言开发

    读取某变量的值(OK HTTP OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .u ...

  3. Android 百度云推送

    http://developer.baidu.com/wiki/index.php?title=docs/cplat/push/sdk/clientsdk. public class DemoAppl ...

  4. java poi 合并单元格

    java poi 合并单元格 2017年03月29日 16:39:01 翠烟你懊恼 阅读数:26561   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.n ...

  5. hdu 4939 三色塔防

    http://acm.hdu.edu.cn/showproblem.php?pid=4939 给出一条长为n个单位长度的直线,每通过一个单位长度需要 t 秒. 有3种塔,红塔可以在当前格子每秒造成 x ...

  6. npm 及安装

    一.npm nodejs使开发者摆脱了浏览器的束缚,一系列基于nodejs的应用和工具不断出现,无论是在node应用的开发,还是使用中,包管理都扮演着一个很重要的作用.NPM(node package ...

  7. JAVA的初始化顺序

    这里主要是介绍JAVA的类的初始化顺序,比较基础:主要是以例子演示为主: 例子一: 1 package com.cnblog.GDUTtiantian; 2 3 /** 4 * 5 * @author ...

  8. hdu 1012 素数判定

    这道题~以前判定prime是一个个去试着整除再去存储,上次弄过欧拉函数那题目之后就知道了,这样会更快捷: prime[] = prime[] = ; ; i <maxn; i++) { if(! ...

  9. mysql数据导入导出方法总结

    MySQL数据备份还原方式总结: 一.将数据导入到指定的数据库 第一种导入方式: (linux下和Windows 下语法是一样的,只是路径的书写方式不同而已) 1.创建一个空数据库 2.进入MySQL ...

  10. ASP.NET Core ef启用数据迁移

    创建一个项目 通过Nuget获取EF Core相关的扩展包 appsettings.json 建立数据库连接串 创建数据库上下文EntityDbContext类,用于实体类映射数据库表 使用包管理器控 ...