1.方法
在Scala中定义函数的最通用方法就是某个对象的成员,这种函数被称为方法:Method
import scala.io.Source object LongLines extends App { 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) } processFile("D:\\ScalaFile.txt",3) }
上面代码被定义在LongLines 中,所以他们是LongLines的方法,processFile负责读取文件,processLine负责读取行判断长度是否符合并且打印输出。
2.本地函数
Scala为了更加详细的描述函数的级别关系,加入了本地函数的概念,也就是函数中的函数
import scala.io.Source object LongLines extends App { def processFile(fileName: String, width: Int) { def processLine(fileName: String, width: Int, line: String) { if (line.length > width) println(fileName + ":" + line.trim) } val source = Source.fromFile(fileName) for (line <- source.getLines()) { processLine(fileName, width, line) } } processFile("D:\\ScalaFile.txt", 3) }
将processLine 移动到processFile里面,让processLine 成为processFile的子函数,processLine的范围只局限性与processFile之内,外部无法访问。
而且在processLine中就可以访问ProcessFile的局部变量,如下代码:
import scala.io.Source object LongLines extends App { 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) } } processFile("D:\\ScalaFile.txt", 3) }
3.第一类函数
Scala的第一类函数与C#的匿名函数lambda一样,如下代码:
object LongLines extends App { val increase = (x: Int) => x + 1 print(increase(12)) }
如果你想在函数文本中输入多行,而函数的返回值就是最后一行产生的那个表达式
object LongLines extends App { val increase = (x: Int) => { println("We") println("are") println("here!") x + 1 } increase(20) }
Scala中提供了很多库来支持他的函数文本,如集合类的foreach表达式:
object LongLines extends App { val list = List(-11,-10,-5,0,5,10) list.foreach { x => println(x) } }
另一个列子是集合类的Filter:
object LongLines extends App { val list = List(-11, -10, -5, 0, 5, 10) list.foreach { x => println(x) } println("Filter") println(list.filter { x => x > 0 }) }
4.函数文本的短格式
Scala提供很多方法使函数文本更加简便如下:
object LongLines extends App { val list = List(-11, -10, -5, 0, 5, 10) list.foreach { x => println(x) } println("Filter") println(list.filter { x => x > 0 }) list.filter(x => x > 0) list.filter(_ > 0) }
_>是最简便的写法,这叫占位符写法,_编译器会生成一个零时的变量,多个_代表多个变量,如下语法:
object LongLines extends App { val add = (_:Int) +(_:Int) println(add(10,5)) }
5.偏应用函数
_还可以替换整个参数列表如下代码:
object LongLines extends App { val list = List(-11, -10, -5, 0, 5, 10) list.foreach(println(_)) //这是一种写法 list.foreach(println _) //这是更方便的写法 list.foreach(println) //这是最简便的方式
}
println _这种写法就是偏应用函数,在Scala里,当你调用函数,传入任何需要的参数,你就是在把函数应用到参数上。如,给定下列函数:
def sum(a: Int, b: Int, c: Int) = a + b + c
你就可以把函数sum应用到参数1,2,3上如sum(1,2,3),偏应用函数是一种表达式,你不需要提供函数需要的所有参数,代之仅提供部分,或者不提供参数:
object LongLines extends App { def sum(a: Int, b: Int, c: Int) = a + b + c val a = sum _ println(a(1,2,3)) }
a(1,2,3)Scala编译器将它编译为a.apply(1,2,3),为什么叫偏应用函数呢?因为函数应用的参数不完全,所以它是偏应用函数,如下:
object LongLines extends App { def sum(a: Int, b: Int, c: Int) = a + b + c val a = sum(1,_:Int,3) println(a(2)) //这里调用的是 sum(1,2,3) println(a(5)) //这里调用的是 sum(1,5,3) }
这样就能看明白了,sum(1,_:Int,3)中间的被占位符所取代了,之后调用的时候只有占位符是未知的,调用sum函数只需要输入占位符所需要的参数就好了。
因为函数应用在参数上不完全,所以叫做偏应用函数。
6.闭包
scala的闭包与C#的闭包是一样的,函数对象使用自由变量时,这个函数被叫做闭包函数:
object LongLines extends App { var more = 1 def addMore(x: Int): Int = x + more println(addMore(1)) }
在这里more 相对于函数 addMore 来说是一个自由变量,而x则是绑定变量,
如addMore(x:Int)=x+1 这个函数就是一个封闭函数,因为他不需要绑定上一个函数堆栈里的内容。
而addMore(x:Int) = x+more 则是一个开放函数,而函数的值是关闭这个开放术语的行动最终产物,所以叫做闭包。
下面就来看看闭包的特性:
object LongLines extends App { var more = 1 val addMore = (x: Int) => { more = 100 x + more } more = 10 println(addMore(10)) println(more) }
输出110,100
7.重复参数
Scala允许你指明函数的最后一个参数是重复的在参数类型后加*就可以,如C#里的params,语法如下:
object LongLines extends App { def outArray(x :String*) = x.foreach(println) outArray("1","2","3","4","5") }
其实scala是吧参数对应成Array[String],但是你如果想直接传入一个Arrary[String]你则需要像下面代码这样:
object LongLines extends App { def outArray(x: String*) = x.foreach(println) outArray(Array("1", "2"): _*) }
添加一个: _*,这样就可以了
更多内容请参考Scala编程