文档章节

Scala基础 - 传名参数和传值参数(by-name/by-value parameter)

joymufeng
 joymufeng
发布于 2016/04/04 21:59
字数 684
阅读 733
收藏 3

1. 介绍

传值参数在函数调用之前表达式会被求值,例如Int,Long等数值参数类型;传名参数在函数调用前表达式不会被求值,而是会被包裹成一个匿名函数作为函数参数传递下去,例如参数类型为无参函数的参数就是传名参数。下文将举例说明这两者的区别。

2. 简单类型的传递示例

2.1 传值参数(by-value parameter)示例

在下面的示例中,编译器检测到strToInt接受一个传值参数,所以先对传入的参数表达式{println("eval parameter expression"); "123"},然后再讲求值结果传递给strToInt。

object Test {
  def strToInt(s: String) = {
    println("call strToInt")
    s.toInt
  }

  def main(args: Array[String]) {
    strToInt({println("eval parameter expression"); "123"})
  }
}
//输出:
eval parameter expression
call strToInt

2.2. 传名参数(by-name parameter)示例

strToInt函数声明中添加一个=>,参数s的类型就变成了无参函数,类型为:() => String,按照Scala针对无参函数的简化规则,此处省略了()。因为参数s的类型是无参函数,所以此处是按名传递。

object Test {
  def strToInt(s: => String) = {
    println("call strToInt")
    s.toInt
  }

  def main(args: Array[String]) {
    strToInt({println("eval parameter expression"); "123"})
  }
}
//输出:
call strToInt
eval parameter expression

从上面的输出可以看出,参数表达式在strToInt函数调用之后才被求值。其实此处编译器自动将参数表达式{println("eval parameter expression"); "123"}转换成匿名的无参函数,并传递给s

3. 复杂类型的传递示例

3.1 传值参数(by-value parameter)示例

invode函数的参数f的类型为柯里化函数String => Int => Long, 此处为按值传递。

object Test {
  def invode(f: String => Int => Long) = {
    println("call invoke")
    f("1")(2)
  }

  def curry(s: String)(i: Int): Long = {
    s.toLong + i.toLong
  }

  def main(args: Array[String]) {
    invode{println("eval parameter expression");curry}
  }
}
//输出:
eval parameter expression
call invoke

3.2 传名参数(by-name parameter)示例

invode函数的参数f的类型为一个无参函数,该无参函数的返回类型为柯里化函数String => Int => Long, 因为参数f的类型是无参函数,所以此处是按名传递。

object Test {
  def invode(f: => String => Int => Long) = {
    println("call invoke")
    f("1")(2)
  }

  def curry(s: String)(i: Int): Long = {
    s.toLong + i.toLong
  }

  def main(args: Array[String]) {
    invode{println("eval parameter expression");curry}
  }
}
//输出:
call invoke
eval parameter expression

4. 小结

如果参数类型是无参函数,则按名传递,否则按值传递。注意,如果参数类型是函数类型,但不是无参函数,还是按值传递,例如:

object Test {
  def strToInt(s: (String) => Int) = {
    println("call strToInt")
    s("123")
  }

  def main(args: Array[String]) {
    strToInt({println("eval parameter expression"); (s: String) => s.toInt})
  }
}
//输出:
eval parameter expression
call strToInt

© 著作权归作者所有

joymufeng

joymufeng

粉丝 100
博文 73
码字总数 67225
作品 2
杨浦
高级程序员
私信 提问
scala:函数参数的传名调用(call-by-name)和传值调用(call-by-value)

问题导读: 1.Scala函数参数传值调用? 2.Scala函数参数传名调用? 引言 Scala的解释器在解析函数参数(function arguments)时有两种方式:先计算参数表达式的值(reduce the arguments),再应...

choulanlan
2016/06/14
0
0
Scala基础 - 柯里化(Currying)及其应用

介绍 柯里化(currying, 以逻辑学家Haskell Brooks Curry的名字命名)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数作为参数的函数。在...

joymufeng
2016/04/04
1K
0
在Scala中函数和方法有什么区别

方法可以作为一个表达式的一部分出现(调用函数并传参),但是方法(带参方法)不能作为最终的表达式, 但是函数可以作为最终的表达式出现: scala> //定义一个方法 scala> def m(x:Int) = ...

如风达
2015/08/28
1K
0
Scala2.10新特性之 Value Classes

Value Classes and Universal Traits http://docs.scala-lang.org/overviews/core/value-classes.html 简介 在Scala中,值类是避免分配运行时对象(avoid allocating runtime objects)的新机......

Ellipse
2013/01/24
1K
4
scala学习(三)

scala类: scala中类定义里,可以放置字段和方法,这些被统称为成员(memeber) 所有成员默认是共有的,如java中默认带public一样 scala中不能定义静态成员,但是可以定义单例对象,用法java的...

如风达
2015/09/07
79
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
1K
14
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
38
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部