scala入门第一坑:变化多端的函数

在scala中,函数具有与变量同等的位置,函数也是一种变量。

1. 函数的定义

函数的定义有两种,一种是使用def定义,另一种是使用val定义。

1.1 第一种定义:使用def

格式:def 函数名(参数名:参数类型)=函数体

def increase(x:Int)=x+1  //这是省略返回类型的写法
def increase(x:Int):Int=x+1  //这是把返回类型也写出来的写法

这是scala给出的本函数的类型

increase: (x: Int)Int
1.2 第一种定义:使用val定义

实质上是把匿名函数赋给一个变量,使这个变量具有函数名的功能
格式:val 函数名=匿名函数,或者用var也行

val increase=(x:Int)=>x+1  //这是一般的写法
val increase=1+(_:Int)  //这是省略变量名的写法
val increase:(Int)=>Int=1+_  //这种写法跟scala给出的函数类型一样

这是scala给出的本函数的类型

increase: Int => Int = <function1>
1.3 方法与函数的区别

注意:使用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失败
<console>:9: error: missing arguments for method m1;

scala> val f1=m1 _  //通过下划线(eta展开),把方法转为函数,这样就可以赋值了,说明下划线可以让方法转化为函数
f1: (Int, Int) => Int = <function2>

2. 高阶函数

普通的函数使用变量作为输入参数和返回值,由于在scala中,函数也属于变量,因此也可以把函数当做输入参数或者返回值,这样的函数成为高阶函数。

2.1 使用函数作为输入参数

格式: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
2.2 使用函数作为输出

格式: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 = <function1>
scala> fun1(2)  //再调用这个函数
res12: Double = 20.0
2.3 闭包

某些函数在定义的时候,除了输入的参数以外,定义内还有一些变量的值未确定,这个变量是外部变量,当这个外部变量被赋值之后,函数的定义才是完整的(闭合),这种函数称为闭包。
其实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  //传入参数

3. 常见的高阶函数

scala里很多内置函数都是高阶函数

3.1 flatMap

是以函数为输入参数的高阶函数
意思大概就是将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
展开阅读全文

没有更多推荐了,返回首页