0.先附上一段示例代码:
package com.heres.scala
/**
* 函数可以被简单的认为是包裹了一条或者几条语句的代码体,该代码体接收若干个参数,经过代码体处理后返回结果,形如数学中的f(x)= x+1
* 在scala中函数是一等公民,可以像变量一样被传递,被赋值,同时函数可以赋值给变量,变量也可以赋值给函数,之所以可以是这样,原因在于
* 函数背后是类和对象,也就是说在运行的时候函数其实是一个变量!!!当然,背后的类是Scala语言自动帮助我们生成的,且可以天然的被序列化和反序列化,
* 这意义非常重要:
* 意义1:可以天然的序列化和反序列化的直接好处就是可以在分布式系统上传递!!!
* 意义2:因为函数背后其实是类和对象,所以可以和普通的变量完全一样的应用在任何普通变量可以运用的地方,包括作为参数传递、作为返回值、被变量赋值
* 和赋值给变量等;
*
* 补充:整个IT编程技术的发展史,其实就是一个封装史:
* 1.Function时代:在c语言中提供了函数的概念,用函数把若干条语句进行封装和复用;
* 2.Class时代:在C++和Java等语言中提供了类和对象,把数据和处理数据的业务逻辑封装起来;
* 3.框架时代:把数据、代码和驱动引擎封装起来,是过去10年和未来10年IT技术的核心
*
* 关于函数初级入门的几个要点:
* a.def关键字来定义函数;
* b.函数会自动进行类型推断来确定函数返回值的类型;如果函数名称和函数体之间没有等号的话则类型推断失效,此时函数的类型是Unit
* c.函数的参数可以是函数
* d.如果 在函数体中无法推导出函数类型,则必须声明具体的类型,
* e.函数的参数可以是默认值,这在实际的编程中意义重大,尤其是在spark等框架中,
* 因为框架一般都有自己的默认配置和实现,此时我们就可以非常好的使用默认值;
* f.我们可以基于函数的参数的名称来调整函数的传递参数的顺序,重点在于为什么可以这么做呢?原因在于函数背后其实是类,其参数就是类的成员,所以无所谓顺序。
* g.函数中如果不确定传递参数的个数,可以使用变长参数的方式;传参时候的一个方便的语法是:_*
* h.可变参数中的数据其实会被收集成为Array数组,我们在入口方面main中其实就是可变参数,是以Array[String]的方式呈现的;
*/
object HelloFunction {
def main(args: Array[String]): Unit = {
//c
println(hello("spark",10))//函数的参数可以是函数
println("fibonacci of 30 = " + fibonacci(30))
hello("scala")
//f
hello(age = 24,name = "heres")
println("result = "+sum(2,3,5,7,8,9))
//g\h
println("result = "+sum(1 to 100: _*))
println("resultdigui = "+sumrec(1 to 100: _*))
}
//b
def hello(name : String,age: Int = 30) ={
println("hello,my name is "+name)
println("hello,my age is "+age)
age
}
//d
def fibonacci(n : Long) : Long ={
if(n <= 1) 1
else fibonacci(n-2) + fibonacci(n-1)
}
def sum(numbers: Int*) ={
var result = 0;
for(number <- numbers) result += number
result
}
def sumrec(numbers: Int*): Int = {
if(0 == numbers.length) 0
else numbers.head + sumrec(numbers.tail: _*)
}
}
1.Scala中的+ - * / %等操作符的作用与Java一样,位操作符 & | ^ >> <<也一样。只是有
一点特别的:这些操作符实际上是方法。例如:
a + b
是如下方法调用的简写:
a.+(b)
a 方法 b可以写成a.方法(b)
2.定义方法(我们看到冒号,就可以知道冒号后面是数据类型。)
3.定义函数
4.如下代码,有另一种定义函数的方法,val m2:Int =>Int = {num => n*n},其中,m2是函数名,第一个Int是输入参数类型,如果是多个,需要加括号;第二个Int是返回值类型;num是输入参数的变量名。
package com.heres.scala
object HelloScala {
val func = (x: Int) => x*3
//另一种定义函数的方法
val startService: Int => Int = {
num => num+1
}
val func2:(Int,Double) => (Double,Int) = {
(x,y) => (y,x)
}
def m1(f: Int => Int): Int ={
f(3)
}
def main(args: Array[String]): Unit = {
val re = m1(func)
println(re)
val arr = Array(1,2,3,4,5,6)
val arr1 = arr.map(x => x*5)
val arr2 = arr.map(x => x-1)
println(arr1.toBuffer)
println(arr2.toBuffer)
println(m1(startService))
}
}
5.方法和函数的区别
在函数式编程语言中,函数是“头等公民”,它可以像任何其他数据类型一样被传递和操作
案例:首先定义一个方法,再定义一个函数,然后将函数传递到方法里面
//定义一个方法
//方法m2参数要求是一个函数,函数的参数必须是两个Int类型
//返回值类型也是Int类型
def m1(f: (Int, Int) => Int) : Int = {
f(2, 6)
}
//定义一个函数f1,参数是两个Int类型,返回值是一个Int类型
val f1 = (x: Int, y: Int) => x + y
//再定义一个函数f2
val f2 = (m: Int, n: Int) => m * n
//main方法
def main(args: Array[String]) {
//调用m1方法,并传入f1函数
val r1 = m1(f1)
println(r1)
//调用m1方法,并传入f2函数
val r2 = m1(f2)
println(r2)
6.4.将方法转换成函数(神奇的下划线)