在scala中,函数具有与变量同等的位置,函数也是一种变量。
函数的定义有两种,一种是使用def定义,另一种是使用val定义。
格式:def 函数名(参数名:参数类型)=函数体
def increase(x:Int)=x+1 //这是省略返回类型的写法
def increase(x:Int):Int=x+1 //这是把返回类型也写出来的写法
这是scala给出的本函数的类型
increase: (x: Int)Int
实质上是把匿名函数赋给一个变量,使这个变量具有函数名的功能
格式:val 函数名=匿名函数,或者用var也行
val increase=(x:Int)=>x+1 //这是一般的写法
val increase=1+(_:Int) //这是省略变量名的写法
val increase:(Int)=>Int=1+_ //这种写法跟scala给出的函数类型一样
这是scala给出的本函数的类型
increase: Int => Int =
注意:使用def定义的函数跟使用val定义的函数,scala给出的函数类型描述是不一样的,是因为二者有本质区别
方法:类的一部分,用def定义
函数:一个完整的对象,用val定义。这里的函数是狭义的函数,之前的函数是广义的函数
二者区别
方法 | 函数 |
---|---|
不是一个值,不可以赋给一个变量 | 是一个值,可以赋给一个变量 |
不可 | 可作为一个参数传入函数(因此高阶函数传入的是一个匿名函数) |
方法名代表方法调用,因此名字后可以不加括号 | 函数名代表函数对象本身,名字后必须加括号才代表函数调用 |
支持参数默认值 | 不支持 |
方法与函数相互转换的方法:
scala> def m1(x:Int,y:Int):Int=x+y //方法m1的定义
m1: (x: Int, y: Int)Int
scala> val f1=m1 //强行赋值给f1失败
:9: error: missing arguments for method m1;
scala> val f1=m1 _ //通过下划线(eta展开),把方法转为函数,这样就可以赋值了,说明下划线可以让方法转化为函数
f1: (Int, Int) => Int =
普通的函数使用变量作为输入参数和返回值,由于在scala中,函数也属于变量,因此也可以把函数当做输入参数或者返回值,这样的函数成为高阶函数。
格式:def 高阶函数名(输入函数名:输入函数类型)=函数体
函数类型的写法参考上面scala给出的函数类型
def convertToString(f:Int=>String)=f(4) //函数体为f(4)代表对输入的函数赋4作为输入参数,但是输入函数具体是什么还未定
def convertToString(f:(Int)=>String)=f(4) //第二种写法
这是scala给出的本函数的类型
convertIntToString: (f: Int => String)String
调用时,输入一个(匿名)函数,就能输出一个值
scala> convertIntToString((x:Int)=>x+" s") //输入一个匿名函数
res32: String = 4 s
格式:def 函数名(参数:参数类型):(函数类型)=函数体
函数体也可以使用匿名函数
def multiplyBy(factor:Double):(Double=>Double)=(x:Double)=>factor*x //完整写法,其中(x:Double)=>factor*x是以x为参数的匿名函数。
def multiplyBy(factor:Double)=(x:Double)=>factor*x //省略函数类型的写法
scala给出的函数类型
multiplyBy: (factor: Double)Double => Double
调用时,对multiplyBy输入factor参数之后,返回一个以x为参数的函数,然后再调用这个函数
scala> val fun1=multiplyBy(10) //返回一个函数
fun1: Double => Double =
scala> fun1(2) //再调用这个函数
res12: Double = 20.0
某些函数在定义的时候,除了输入的参数以外,定义内还有一些变量的值未确定,这个变量是外部变量,当这个外部变量被赋值之后,函数的定义才是完整的(闭合),这种函数称为闭包。
其实2.2函数体内的匿名函数就是一个闭包,外部变量是factor
(x:Double)=>factor*x //外部变量factor赋值后,此匿名函数的定义才是完整的
scala> val fun1=multiplyBy(10) //这就相当于给factor赋值
2.1的f不算是外部变量,它是传入的参数,在定义中它肯定是不用被赋值的,所以2.1的函数不算闭包
def convertToString(f:Int=>String)=f(4) //f是需要传入的参数convertIntToString: (f: Int => String)String //传入参数
scala里很多内置函数都是高阶函数
是以函数为输入参数的高阶函数
意思大概就是将f这个函数应用到Seq里的所有元素,并将函数产生的集合里的元素取出来,组成一个新的集合,然后返回这个新的集合
def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Seq[B]
Builds a new collection by applying a function to all elements of this sequence and using the elements of the resulting collections.
//输入的函数类型 (A) ⇒ GenTraversableOnce[B]
//返回值类型是一个Seq Seq[B]
它不是一个单独的函数,而是一个类的方法(具体哪个类我不知道?),所以调用是需要在前面加对象,再用 . . .来调用,一般用于其他函数定义的函数体内
def getWords(lines: Seq[String]): Seq[String] = lines.flatMap(line => line.split(" ")) //给flatMap输入一个匿名函数,
val e = Seq("I love","coding scala")
getWords(e).foreach(println(_))
//返回值是
I
love
coding
scala