scala 函数(一) - 6

类成员函数

常见的定义函数的方法:

import scala.io.Source
object LongLines{
	def processFile(filename:String, width: Int) {
		val source = Source.fromFile(filename)
		for(line <- source.getLines())
			processLine(filename,width,line)
	}
	
	private def processLine(filename: String, width:Int, line:String)
	{
		if(line.length > width)
			println(filename + ":" +line.trim)
	}
}

局部函数

可以在函数的内部再定义函数,如同定义一个局部变量

私有成员函数 processLine 移动到 processFile 内部,成为了一个局部函数。也正因为如此, processLine 可以直接访问到 processFile 的参数 filename 和 width

object LongLines {
def processFile(filename: String, width: Int) {
def processLine(line:String){
if(line.length > width)
println(filename + “:” +line.trim)
}

val source= Source.fromFile(filename)
for (line <- source.getLines())
    processLine(line)
}

}

头等公民

函数是头等公民,不仅可以定义一个函数然后调用它,还可以写一个未命名的函数字面量,然后把它当成一个值,传递到其他函数或是赋给其他变量。

scala> var increase = (x:Int) => x+1
increase: Int => Int =

注意,函数字面量 (x:Int) => x + 1 在 Scala 内部,表示为带有一个参数的类 function1 的一个对象。其它情况比如 functionN 代表带有 N 个参数的函数, function0 代表不含参数的函数类型。

scala 的库允许使用函数作为参数

Scala 还可以进一步简化:Scala 允许使用“占位符”下划线“_”来替代一个或多个参数,只要这个参数值函数定义中只出现一次,Scala 编译器可以推断出参数。比如:

scala> val someNumbers = List ( -11, -10, - 5, 0, 5, 10)
someNumbers: List[Int] = List(-11, -10, -5, 0, 5, 10)

scala> someNumbers.filter( _ >0)
res0: List[Int] = List(5, 10)

就像我们以前做过的填空题,“ _ ”为要填的空
Scala 会来完成这个填空题,而你来定义填空题
因为 下划线 替代的参数在函数体中只能出现一次
因此多个代表多个参数。
第一个代表第一个参数
第二个代表第二个参数,以此类推。

部分应用的函数

一个部分应用函数是指在调用函数时,不指定函数所需的所有参数。这样你就创建了一个新的函数。

比如 固定sum的第一和第三个参数:
scala> def sum = (:Int) + ( :Int) + (_ :Int)
sum: (Int, Int, Int) => Int

scala> val b = sum (1, _:Int, 3)
b: Int => Int =

scala> b(2)
res24: Int = 6

变量b的类型为一个函数,具体类型为function1(带一个参数的函数),它是由sum应用了第一个参数和第三个参数构成的。

闭包

假设我们定义如下函数
scala> var more = 1
val addMore = (x:Int) => x + more
more: Int = 1
addMore: Int => Int =

scala> addMore(100)
res26: Int = 101

这样定义的函数变量addMore是一个闭包,他引用了函数外面定义的变量。定义这个函数的过程,是将这个自由变量捕获而构成的一个封闭函数。

scala的闭包捕获的是变量本身而不是当时的变量的值。 引用传递。

在闭包里面修改引用的值,其结果可以传到闭包的外面

如果一个闭包所访问的变量有几个版本,比如一个闭包使用了一个函数的局部变量,然后这个函数调用了很多次,那么返回结果相同。闭包所引用的变量为定义该闭包时的变量的值,也就是定义闭包时相当于保存了当时程序状态的一个快照。

可变参数、命名参数、缺省参数

重复参数

  • 允许最后一个参数重复(变长参数),从而允许函数调用者使用变长参数列表来调用该函数
  • scala使用“*”来指明该参数为重复参数。

scala> def echo (args:String *) =
| for (arg <- args) println(arg)

echo: (args: String*)Unit

scala> echo(“one”,“Two”)
one
Two

变长参数的类型实际上是一个数组,上例中的String * 类型实际为Array[String].但是直接传array数组会报错
scala> val arr = Array(“one”,“two”)
arr: Array[String] = Array(one, two)

scala> echo(arr)
:13: error: type mismatch;
found : Array[String]
required: String
echo(arr)

为了避免该情况发生,可以在变量后面加 * 。告诉编译器逐个传入数组的参数,而不是将数组整个一起传入。
scala> echo (arr:
*)
one
two

命名参数

通常情况,函数传入和函数定义时的参数列表是一一对应的
但是使用命名参数是,允许你使用任意顺序传入参数
scala> def speed (distance:Float, time:Float) :Float = distance/time
speed: (distance: Float, time: Float)Float

scala> speed(100,1)
res38: Float = 100.0

scala> speed(time = 1,distance = 100)
res39: Float = 100.0

缺省参数值

通常和命名参数一起使用
scala> def printTime(out:java.io.PrintStream = Console.out, divisor:Int = 1) = out.println("time = " + System.currentTimeMillis()/divisor)
printTime: (out: java.io.PrintStream, divisor: Int)Unit

scala> printTime()
time = 1548034240186

scala> printTime(divisor = 1000)
time = 1548034255

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值