Scala混合了面向对象和函数式的特性,我们通常将可以作为参数传递到方法中的表达式叫做函数。在函数式编程语言中,函数是“头等公民”,高阶函数包含:作为值的函数、匿名函数、闭包、柯里化等等。
可以像任何其他数据类型一样被传递和操作的函数,每当你想要给算法传入具体动作时,这个特性就会变得非常有用。
scala>val arr = Array(1,2,3,4,5) arr:Array[Int] = Array(1,2,3,4,5) //定义一个函数,并将函数赋值给变量fun1 scala> val fun1 = (x:Int) => x * 2 fun1:Int => Int = <function1> //将函数作为参数传入map方法中 scala>arr.map(fun1) res0:Array[Int] = Array(2,4,6,8,10)定义函数时格式:val 变量名 = (输入参数类型和个数)=> 函数实现和返回值类型 “=” 表示将函数赋给一个变量。 => 左边表示输入参数名称、类型和个数,右边表示函数的实现和返回值类型。
在Scala中,你不需要给每一个函数命名,没有将函数赋值给变量的函叫做匿名函数。
scala>arr.map((x:Int) => x * 2) res2:Array[Int] = Array(2,4,6,8,10)由于Scala可以自动推断出参数的类型,因此可以写得更精简些。
scala>arr.map(x => x * 2) res3:Array[Int] = Array(2,4,6,8,10)神器的下划线,这样更精简
scala>arr.map(_*2) res4:Array[Int] = Array(2,4,6,8,10)柯里化(Currying):将接收多个参数的方法,转换为接收一个参数的函数的过程 => 返回值是一个函数,参数就是其余参数,而且第一个参数的值会累计在此函数中。
//一个比较奇怪的方法,看起来即像方法又像函数 scala> def m(x:Int) = (y:Int) => x * y m:(x:Int)Int => Int //将一个参数3传进函数后,彻底变成一个函数.val func = (y:Int) => 3 * y scala> val func = m(3) func:Int => Int = <function1> //然后调用这个函数并传递第二个参数,得到最终结果 scala>func(5) res3:Int - 15 //在Scala中这样的函数可以简写成def m(x:Int)(y:Int) = x * y scala>m(3)(5) res4:Int = 15当你调用curriedSum(1)(2)时,实际上是依次调用两个普通函数(非柯里化函数),第一次调用使用一个参数x,返回一个函数类型的值;第二次使用参数y调用这个函数类型的值。
使用“柯里化”技术来定义这个加法函数,原来函数使用一个参数列表,“柯里化”,把函数定义为多个参数列表: //首先定义第一个函数: scala> def first(x:Int)=(y:Int)=>x+y first: (x: Int)Int => Int //然后我们使用参数1调用这个函数来生成第二个函数: scala> val second =first(1) second: Int => Int = <function1> scala> second(2) res2: Int = 3 使用curriedSum来定义second scala> val onePlus=curriedSum(1)_ onePlus: Int => Int = <function1> //下划线“_” 作为第二参数列表的占位符, 这个定义的返回值为一个函数,当调用时会给调用的参数加一。 scala> onePlus(2) res3: Int = 3 //调用生成的函数,给函数传入参数,即可得到我们想要的结果。scala柯里化风格的使用可以简化主函数的复杂度,提高主函数的自闭性,提高功能上的可扩展性、灵活性。可以编写出更加抽象,功能化和高效的函数式代码。
就是函数的返回值依赖于函数之外的参数