scala 函数用法

函数的声明

scala 函数通过 def 关键字定义,def前面可以具有修饰符,可以通过private、protected来控制其访问权限。
注意:没有public,不写默认就是public的。 此外也可跟上override,final等关键字修饰。

函数的返回值

1)函数体中return关键字往往可以省略掉,一旦省略掉,函数将会返回整个函数体中最后一行表达式的值,这也要求整个函数体的最后一行必须是正确类型的值的表达式。 2)大部分时候scala都可以通过 =符号 来自动推断出返回值的类型,所以通常返回值类型声明可以省略。
但是注意:如果因为省略了返回值类型造成歧义,则一定要写上返回值声明。
3)如果函数体只有一行内容,则包裹函数体的大括号可以省略
4)如果返回值类型是UNIT,则另一种写法是可以去掉返回值类型和等号,把方法体写在花括号内,而这时方法内无论返回什么,返回值都是 UNIT。

格式:[private/protected] def 函数名(参数列表):返回值声明 = {函数体}
示例:

//方法的返回值为空
def f1():Unit={ println("hello scala");
}

//等价于f1()方法,注意:如果函数没有=号,无论函数体里的返回值是什么,函数的返回值

都是Unit

def f2(){
println("hello scala");
}
//定义方法参数类型,返回值类型,及返回值
def f3(a:Int,b:Int):Int={ a+b;
}


//scala可自行推断返回值类型,所以可省略返回值类型
def f4(a:Int,b:Int)={ a+b;
}
//如果函数体只一行内容,可以省了花括号
def f5(a:Int,b:Int)=a+b


//注意下面这种形式,因为没有=号,所以函数的返回值是Unit,即()
def f6(a:Int,b:Int){ a+b
}

默认参数
代码示意:

object Demo21 {

def f1(a:String,b:String="[",c:String="]")={ b+a+c
}

def main(args: Array[String]): Unit = { print(f1("hello"))//将打印:[hello]
}

}

函数的种类

1.成员函数
2.本地函数(内嵌在函数内的函数)
3.函数值(匿名函数)
4.高阶函数

成员函数: 函数被使用在类的内部,作为类的一份子,称为类的成员函数
示例:

object Demo15 {


def main(args: Array[String]): Unit = { val p=new Student();
p.eat();
p.study();
}

// eat() 和study()属于 类Student的成员函数
class Student{ def eat(){
println("吃饭")
}


def study(){
println("学习")
}
}

}

本地函数:函数内嵌的函数称为本地函数,这样的函数外界无法访问示例:
object Demo16 {

def main(args: Array[String]): Unit = { val p=new Student();
p.eat(“肉”);

}

class Student{

def eat(food:String){
//cook函数内嵌在eat函数里,这样的函数称之为本地函数
def cook(food:String):String={
“做熟了的”+food;
}
println(“吃”+cook(food));
}

}

}

函数值 - 匿名函数: 示例:

def f1(a:Int,b:Int):Int={a+b};


//等价于上式的函数
(a:Int,b:Int)=>{a+b};


//如果函数体只有一行代码,可以省去大括号
(a:Int,b:Int)=>a+b;


//如果函数参数列表只有一个参数,小括号有可以省略

a:Int=>a+1;


//如果函数的参数类型可以被推测,则可以省略类型值
//(a,b)=>a+b


def f1(a:Int,b:Int):Int={a+b};
//可以将f1()函数赋值给f2常量
val f2=f1(_,_);


//可以将f1()函数赋值给f3变量,f3可以更改此函数
var f3=f1(_,_); f3=(a:Int,b:Int)=>a*b;

//也可以这样写
val f4=(c:Int,d:Int)=>{c+d}


//注意,下面的写法是将f1的函数值复制给f5,而不是函数赋值给f5
val f5=f1(2,3)
高阶函数:函数可以作为方法的参数进行传递和调用

示例1:

object Demo01 {
//定义了compute函数,a,b和f函数 三个参数。其中f函数未做实现。
//我们的目的是对传入的a和b参数利用 f函数做运算,但是具体是什么运算需要由用户自己来指定。
def compute(a:Int,b:Int,f:(Int,Int)=>Int):Int={ f(a,b)
}   

def main(args: Array[String]): Unit = {
val f1=(a:Int,b:Int)=>{a+b} val f2=(a:Int,b:Int)=>{a*b} val f3=(a:Int,b:Int)=>{a-b} val f4=(a:Int,b:Int)=>{a/b}

//由下式可以看出,scala中,函数可以当做参数进行传递和调用
val result=compute(2,3,f1)      
//下式等价于上式
//val result=compute(2,3,(a,b)=>{a+b})
}    
}

示例2:

object Demo02 {
//定义了一个函数,作用是将用户处理后的字符串结果进行打印输出def                
handleString(a:String,f:(String)=>String){ println("处理完后的字符串为:"+ f(a))
}
def main(args: Array[String]): Unit = { val a="hello scala";
handleString(a,(a)=>{a}); handleString(a,(a)=>{a.substring(6)}); handleString(a,(a)=>{a.concat(" 1706")})
}
}

占位符:占位符指的是scala中的下划线_ ,可以用它当作一个或多个参数来使用。
使用_占位符的前提要求:每个参数在函数仅出现一次。
使用下划线时,如果类型可以自动推断出,则不用声明类型。如果无法自动推断类型,则在下划线后自己来显示声明类型即可。
示例1:

object Demo03 {
def compute(a:Int,b:Int,f:(Int,Int)=>Int):Int={ f(a,b)
}
def handleString(a:String,f:(String)=>String){
println("处理完后的字符串为:"+ f(a))
}
def main(args: Array[String]): Unit = { val message="hello scala";
//这样用占位符会报错
//handleString(message,(_)=>{_.substring(6)})

//应改为下面的写法
handleString(message,{_.substring(6)})

//如果函数体只有一行代码,则还可以将大括号去掉
handleString(message,_.substring(6))

//compute的代码可简化如下compute(2,3,_+_) compute(2,3,_*_)
compute(2,3,_-_)


//	此外
//	val f1=(a:Int,b:Int)=>{a+b}
//	等价于下式:
//	val f1=(_:Int)+(_:Int)
//	compute(2, 3, f1)
//再来看一个例子
val list=List(1,3,5,7,9)


list.foreach { x =>print(x) } list.foreach { _ =>print(_) } list.foreach { print(_) }

list.foreach { x => x*2 } list.foreach { _*2 }      
   }
  }

递归

示例1:
object Demo07 {

//从1开始做加法,只加偶数,当加和累计超过50时,结束递归
//示意:2+4+6……

def f1(num:Int,sum:Int):Int={ if(sum>50) return sum; if(num%2==0){f1(num+1,sum+num)} else {f1(num+1,sum)}

}
def main(args: Array[String]): Unit = {
//num是用户传入的初始值=1,sum是最后求得的和,初始值是0 val result=f1(1,0)
println(result)
}
}

示例2,用递归方式实现斐波那契数列

//0 1 1 2 3 5 8 13
def f2(n:Int):Int={
if(n==0) return 0
if(n==1) return 1 else f2(n-1)+f2(n-2)
} f2(6)

示 例 3——2 3 4 9 16 81 ?

// n的取值:f(0) f(1) f(2) f(3) f(4) f(5)
//当n为偶数时,f(n)=f(n-2)*f(n-2)

//当n为奇数是,f(n)=f(n-2)*f(n-2)


def f3(n:Int):Int={
if(n==0) return 2
if(n==1) return 3 else f3(n-2)*f3(n-2)
}

示例4——函数值:2 3 4 9 8 27 16 ?

//当n为偶数时,f(n)=2*f(n-2)
//当n为奇数是,f(n)=3*f(n-2)


def f4(n:Int):Int={
if(n==0) return 2
if(n==1) return 3


if(n%2==0)2*f4(n-2) else 3*f4(n-2)
}

示例5——求 1~n的数字之和

//1   3	6	10	15
//f(0) f(1) f(2) f(3) f(4)
//f(n)=f(n-1)+n+1


def f5(n:Int):Int={
if(n==0) return 1 else f5(n-1)+n+1
}

示例6—给定一个初始值n,并设定sum的初始值为0,当求和sum>12时结束递归

//0 1 3 6 10 15
//f(0,0)——n=0,sum=0
//f(1,1)——n=1,sum=1
//f(2,3)——n=2,sum=3

//f(3,6)——n=3,sum=6
//f(n+1,sum+n)
def f6(n:Int,sum:Int):Int={ if(sum>12)return sum else f6(n+1,sum+n)
}	//> f6: (n: Int, sum: Int)Int    
    f6(0,0)	//> res3: Int = 15

示例7:

//给定一个scope范围,计算0~scope范围的整数之和,
//当和>12或者达到scope边界时,结束递归def f7(n:Int,sum:Int,scope:Int):Int={
if(sum>12)return sum if(n-1==scope)return sum else f7(n+1,sum+n,scope)

}	//> f7: (n: Int, sum: Int, scope: Int)Int f7(0,0,4)		//> res4: Int = 10

scala中,如果在递归时,保证函数体的最后一行为递归调用,则称这样的递归为尾递归。scala会针对尾递归做优化处理,所以建议在写递归时写成尾递归形式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值