一.函数
函数声明
def functionName ([list of parameters]) : [return type]
1.定义无输入的函数
示例:
def hi="hi" scala>hi def hi():String="hi" scala>hi() scala>hi
2.定义函数
def functionName ([list of parameters]) : [return type] = { function body return [expr] }
示例:
//最后一行是函数的返回值 def multiplier(x:Int,y:Int):Int={x*y} def safeTrim(s:String):String={ if (s==null) return null s.trim() }
3.过程
过程是没有返回值的函数。以一个语句(如println()调用)结尾的函数也是一个过程。
返回类型为Unit 表示没有值。
示例:
def log(d:Double)=println(f"Got value $d%.2f") def log(d:Double):Unit=println(f"Got value $d%.2f")
4.用表达式块调用函数
使用一个参数调用函数时,可以利用一个大括号包围表达式发送参数,而不是用小括号包围值。
示例:
def formatEuro(amt:Double)=f"$amt%.2f" scala>formatEuro{val rate;0.2*rate+0.3}
5.递归函数
递归函数就是调用函数自身的函数,需要注意避免陷入无限循环。
示例:
def power(x:Int,n:Int):Long={ if(n>=1) x*power(x,n-1) else 1 }
6.嵌套函数
可以在函数中定义另一个内部函数,这个内部函数只能在该函数中使用。
示例:
def max(a:Int,b:Int,c:Int)={ def max(x:Int,y:Int)=if(x>y) x else y max(a,max(b,c)) }
7.用命名参数调用函数
在Scala中,可以按名调用参数,这样就不一定要按顺序指定参数。
示例:
def greet(orefix:String,name:String)=s"$prefix $name" val greeting=greet(name="Brown",prefix="Mr")
8.为函数参数指定默认值
示例:
def greet(name:String,orefix:String="")=s"$prefix $name" val greeting=greet("Brown")
9.Vararg参数
要标志一个参数匹配一个或多个输入实参,在函数定义中需要该参数类型后面增加一个星号(*)
示例:
def sum(items:Int*):Int={ var total=0 for(i<-items) total+=i total } scala>sum() res1:Int =0 scala>sum(10,20,30) res2:Int=60
10.参数组
把参数表分解为参数组,每个参数组分别用小括号分隔。
示例:
def max(x:Int)(y:Int)=if(x>y) x else y val larger=max(20)(19)
11.类型参数
类型参数指示了值参数或返回值使用类型,函数参数或返回值的类型不再固定。可以由函数调用者设置。
示例:
def identity[A](a:A):A=a val s:String=identity[String]("hello") val d:Double=identity[Double](2.345) //类型推导:Scala编译器可以推导出类型参数的类型,以及将赋为返回值的值的类型。 val s=identity("hello") val d=identity(2.345)
二.首类函数
“首类”表示函数不仅能得到声明和调用,还可以作为一个数据类型用在这个语言的任何地方。
1.函数类型
([<type>,...})=><type> , 有单个参数的函数类型可以省略小括号.
示例:
def double(x:Int):Int=x*2 val myDouble:(Int)=>Int=double myDouble(5) def logStart()="hello" val start:()=>String=logStart start()2.用通配符为函数赋值
示例:
def double(x:Int):Int=x*2 val myDouble=double_ myDouble(20)3.高阶函数
包含一个函数类型的值作为输入参数或返回值的函数
示例:
//定义带函数类型的值作为参数的函数 def safeStringOp(s:String,f:String=>String)={ if(s!=null) f(s) else s } def reverser(s:String)=s.reverse //调用函数 safeStringOp("Ready",reverser)4.函数字面量
示例:
val doubler=(x:Int)=>x*2 val doubled=doubler(20) val greeter=(name:String)=>s"Hello,$name" val hi=greeter("World") //3中例子可写成 safeStringOp("Ready",(s:String)=>s.reverse)5.占位符语法
占位符语法是函数字面量的一种缩写形式,将命名参数替换为通配符(_)。
示例:
val doubler:Int=>Int=_*2 //3中例子可写成 safeStringOp("Ready",_.reverse) def combination(x:Int,y:Int,f:(Int,Int)=>Int)=f(x,y) combination(23,12,_*_) res:Int=276 def tripleOp[A,B](a:A,b:A,c:A,f:(A,A,A)=>B)=f(a,b,c) tripleOp[Int,Double](23,92,14,1.0*_/_/_)6.部分应用函数
想重用一个函数,而且希望保留一些参数不想再次输入实,可以部分应用函数。
示例:
def factorOf(x:Int,y:Int)=y%x==0 //部分应用 val multipleOf=factorOf(3,_:Int) val y=multipleOf(78) val isEven=factorOf(2)_ val z=isEven(32)7.传名参数 在函数中使用一个传名参数时,它会计算为一个值。如果向这个函数传入一个值,不会有任何作用,不过,如果向它传入一个函数,那么每次使用时都会调用这个函数。
示例:
def doubles(x:=>Int)={ println("Now doubling"+x) x*2 } doubles(5) 运行结果: Now doubling 5 res:Int=10 def f(i:Int)={println(s"Hello from f($i)");i} double(f(8)) 运行结果: Hello from f(8) Now Double 8 Hello from f(8) res:Int=16注:参考《Scala 学习手册》