package chapter05
object Test01_FunctionAndMethod {
def main(args: Array[String]): Unit = {
//定义函数
def sayHi(name:String):Unit={
println("hi,"+name)
}
//调用函数
sayHi("alice")
//调用对象方法
Test01_FunctionAndMethod.sayHi("bob")
//获取对象返回值
val result = Test01_FunctionAndMethod.sayHello("cary")
println(result)
}
//定义对象的方法
def sayHi(name:String):Unit={
println("Hi,"+name)
}
def sayHello(name:String):String={
println("Hello,"+name)
return "hello"
}
}
package chapter05
object Test02_FunctionDefine {
def main(args: Array[String]): Unit = {
// (1) 函数 1:无参,无返回值
def f1():Unit={
println("1:无参,无返回值")
}
f1()
println(f1())
println("-------------------------------------------")
// (2) 函数 2:无参,有返回值
def f2():Int={
println("2:无参,有返回值")
return 12
}
println(f2())
println("--------------------------------------")
// (3) 函数 3:有参,无返回值
def f3(name:String):Unit={
println("3:有参,无返回值"+name)
}
println(f3("alice"))
println("--------------------------------------------")
// (4) 函数 4:有参,有返回值
def f4(name:String):String={
println("4:有参,有返回值"+name)
return "hi,"+name
}
println(f4("alice"))
println("---------------------------------")
// (5) 函数 5:多参,无返回值
def f5(name1:String,name2:String):Unit={
println("5:多参,无返回值")
println(s"${name1}和${name2}都是我的好朋友")
}
f5("alice","bob")
println("------------------------------------------")
// (6) 函数 6:多参,有返回值
def f6(a:Int,b:Int):Int={
println("6:多参,有返回值")
return a+b
}
println(f6(12,37))
}
}
package chapter05
object Test03_FunctionParameter {
def main(args: Array[String]): Unit = {
// (1) 可变参数 WrappedArray包装起来的数组 Scala抽象的集合类型
def f1(str:String*):Unit={
println(str)
}
f1("alice")
f1("aaa","bbb","ccc")
println("-------------------------------------")
// (2) 如果参数列表中存在多个参数,那么可变参数一般放置在最后 *归属于最后
def f2(str1:String,str2:String*):Unit={
println("str1:"+str1+"\t str2:"+str2)
}
f2("alice")
f2("aaa","bbb","ccc")
println("------------------------------------------")
// (3) 参数默认值,一般将有默认值的参数放置在参数列表的后面
def f3(name:String="bigdata"):Unit={
println("my school is "+name)
}
f3("school")
f3()
println("------------------------------------------")
// (4) 带名参数 有默认值时比较常用
def f4(name:String="bd",age:Int):Unit={
println(s"${age}岁的${name}在学习大数据")
}
f4("zhangsan",22)
f4(age=23,name="lisi")
f4(age=25)
}
}
package chapter05
//函数至简原则
object Test04_Simplify {
def main(args: Array[String]): Unit = {
def f0(name:String):String={
return name
}
println("bd")
println("--------------------------------------")
// (1) return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
def f1(name:String):String={
name
}
println(f1("zs"))
println("-------------------------------------------------")
// (2) 如果函数体只有一行代码,可以省略花括号
def f2(name:String):String =name
println("zs")
println("---------------------------------------")
// (3) 返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
//函数式编程 关注的就是数学上的映射关系
def f3(name:String)=name
println("zs")
println("-----------------------------------")
// (4) 如果有 return,则不能省略返回值类型,必须指定
//要省略 一起省略
def f4(name:String)={
name
}
println("bd")
println("--------------------------------------")
// (5) 如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
def f5(name:String):Unit={
return name
}
println("bd")
println("--------------------------------")
// (6) Scala 如果期望是无返回值类型,可以省略等号
def f6(name:String){
println(name)
}
// (7) 如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
def f7():Unit={
println("kkxx")
}
f7()
f7
println("------------------------------")
// (8) 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
def f8:Unit={
println("kkll")
}
f8
println("-------------------------------")
// (9) 如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
def f9(name:String):Unit={
println(name)
}
//匿名函数 lambda表达式
(name:String)=>{println(name)}
}
}
package chapter05
object Test05_Lambda {
def main(args: Array[String]): Unit = {
val fun=(name:String)=> {println(name)}
fun("zhangsan")
println("---------------------------")
//定义一个函数,以函数作为参数输入
def f(func:String=>Unit):Unit={
func("lisi")
}
f(fun)
f((name:String)=> {println(name)})
println("---------------------------------")
//匿名函数的简化原则
// (1) 参数的类型可以省略,会根据形参进行自动的推导
f((name)=>{
println(name)
})
// (2) 类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参
// 数超过 1 的永远不能省略圆括号。
f(name =>{
println(name)
})
// (3) 匿名函数如果只有一行,则大括号也可以省略
f(name =>println(name))
// (4) 如果参数只出现一次,则参数省略且后面参数可以用_代替
f(println(_))
// (5) 如果可以推断出 当前传入的println是一个函数体 而不是调用语句 可以直接省略下划线
f(println)
println("-----------------------------------------")
//实际示例,定义一个"二元运算“函数,只操作1和2两个数,但是具体运算通过参数传入
def dualFunctionOneAndTwo(fun:(Int,Int)=>Int):Int={
fun(1,2) //这里1,2直接写死 只能调用1,2
}
val add=(a:Int,b:Int)=>a+b
val minus=(a:Int,b:Int)=>a-b
println(dualFunctionOneAndTwo(add))
println(dualFunctionOneAndTwo(minus))
println("---------------------------------")
//匿名函数简化
println(dualFunctionOneAndTwo((a:Int,b:Int)=>a+b)) //fun Int Int已经写死了 不用再定义Int
println(dualFunctionOneAndTwo((a:Int,b:Int)=>a-b))
println("---------------------------------")
println(dualFunctionOneAndTwo((a,b)=>a+b))
println(dualFunctionOneAndTwo(_+_))
println(dualFunctionOneAndTwo(_-_))
println("--------------------------------------")
println(dualFunctionOneAndTwo((a,b)=>b-a)) //-a+b
println(dualFunctionOneAndTwo(-_+_))
}
}
package chapter05
object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
def f(n:Int):Int={ //最简单的函数声明和调用
println("f调用")
n+1
}
def fun():Int={
println("fun调用")
1
}
val result:Int=f(123)
println(result)
fun()
fun
println("---------------------------------------")
//1.函数可以作为值进行传递
val f1:Int=>Int=f
val f2 =f _
println(f1)
println(f1(12))
println("--------------------------------------")
println(f2)
println(f2(35))
println("----------------------------------------")
// val f3=fun //引用
//此时f3 f4 都为函数
val f3:()=>Int=fun
val f4=fun _
println(f3)
println(f4)
println("---------------------------------------")
//2.函数作为参数进行传递
//定义二元计算函数
//两个int类型的参数 得到一个int类型的返回值 传入的数据是什么
def dualEval(op:(Int,Int)=>Int,a:Int,b:Int):Int={
op(a,b)
}
def add(a:Int,b:Int):Int={
a+b
}
println(dualEval(add,12,35))
println(dualEval((a,b)=>a+b,12,35))
println(dualEval(_+_,12,35))
//3.函数作为函数的返回值返回
def f5(): Int=>Unit={
def f6(a:Int):Unit={
println("f6调用"+a)
}
f6 //将函数直接返回
}
println(f5()) //返回的是函数f6
println("---------------------------")
val f6=f5()
println(f6)
println(f6(25)) //()是f6本身没有返回值 Unit
println("----------------------------")
println(f5()(25))
}
}
package chapter05
object Test07_Practice_CollectionOperation {
def main(args: Array[String]): Unit = {
val arr:Array[Int]=Array(12,45,75,98)
//对数组进行处理,将操作抽象出来,处理完毕之后的结果返回一个新的数组
def arrayOperation(array:Array[Int],op:Int=>Int):Array[Int]={
for(elem <- array) yield op(elem)
} //对op进行操作 返回一个新的数组
//定义一个加一操作
def addOne(elem:Int):Int={
elem+1
}
//调用函数
val newArray:Array[Int]=arrayOperation(arr,addOne)
println(newArray.mkString(","))
//传入匿名函数,实现元素翻倍
val newArray2=arrayOperation(arr,_*2) //(arr,elem=>elem*2)
println(newArray2.mkString(","))
}
}
package chapter05
object Test08_Practice {
def main(args: Array[String]): Unit = {
//练习1
val fun =(i:Int,s:String,c:Char) =>
{if(i==0 && s=="" && c=='0') false else true}
println(fun(0,"",'0'))
println(fun(0,"",'1'))
println(fun(23,"",'0'))
println(fun(0,"hello",'0'))
println("------------------------------------")
//2.练习2
def func(i:Int):String=>(Char=>Boolean)={ //嵌套 内层函数保存下来
def f1(s:String):Char=>Boolean ={
def f2(c:Char):Boolean = {
if(i==0 && s=="" && c=='0') false else true
}
f2
}
f1 //整体返回
}
println(func(0)("")('0'))
println(func(0)("")('1'))
println(func(23)("")('0'))
println(func(0)("hello")('0'))
println("-------------------------------------")
//匿名函数简写
def func1(i:Int):String=>(Char=>Boolean)={
s => c =>if(i==0 && s=="" && c=='0') false else true
} //内层函数可以直接使用外层函数的参数的 相当于外层定义好的参数和变量 可以传递到内层函数里面去做处理
println(func1(0)("")('0'))
println(func1(0)("")('1'))
println(func1(23)("")('0'))
println(func1(0)("hello")('0'))
//底层有相关的打包和优化时 可以放在一起 就是闭包
println("-------------------------------------")
//柯里化
def func2(i:Int)(s:String)(c:Char):Boolean={
if(i==0 && s=="" && c=='0') false else true
}
println(func2(0)("")('0'))
println(func2(0)("")('1'))
println(func2(23)("")('0'))
println(func2(0)("hello")('0'))
}
}
package chapter05
//闭包 柯里化
object Test09_ClosureAndCurrying {
def main(args: Array[String]): Unit = {
def add(a:Int,b:Int):Int={
a+b
}
//1.考虑固定一个加数的场景
def addByFour(b:Int):Int={
4+b
}
//2.扩展固定加数改变的情况
def addByFive(b:Int):Int={
5+b
}
//3.将固定加数作为另一个参数传入,但是是作为“第一层参数”传入 万能钥匙->百能钥匙
def addByFour1():Int=>Int={ //内层函数用到了外层函数的一个局部变量
val a=4
def addB(b:Int):Int={
a+b
}
addB
}
def addByA(a:Int):Int=>Int ={
def addB(b:Int):Int={
a+b
}
addB
}
println(addByA(35)(24))
println("----------------------------------")
val addByFour2=addByA(4)
val addByFive2=addByA(5)
println(addByFour2(13))
println(addByFive2(25))
//4.lambda表达式简写 闭包
def addByA1(a:Int):Int=>Int={
(b:Int)=>{
a+b
}
}
def addByA2(a:Int):Int=>Int={
b => a+b
}
def addByA3(a:Int):Int=>Int=a + _
val addByFour3=addByA3(4)
val addByFive3=addByA3(5)
println(addByFour3(13))
println(addByFive3(25))
println("-----------------------------")
//5.柯里化
def addCurrying(a:Int)(b:Int):Int={ //分层调用 一旦用到柯里化 底层一定是闭包
a+b
}
println(addCurrying(35)(24))
}
}
package chapter05
import scala.annotation.tailrec
object Test10_Recursion {
def main(args: Array[String]): Unit = {
println(fact(5))
println(tailFact(5))
}
//递归实现计算阶乘 纯函数编程语言可以只使用递归 但耗费栈资源
//一次次覆盖 不耗费栈资源
def fact(n:Int):Int={
if(n==0) return 1
fact(n-1)*n
}
//尾递归实现 java可以写成尾递归的形式 但是却是无效的 尾递归的优化是依赖编译器的
//需要编译器知道 在栈帧里面覆盖 而不是做压栈
//真正的函数式语言 都会支持尾递归的
def tailFact(n:Int):Int={
@tailrec
def loop(n:Int,currRes: Int):Int={
if(n==0) return currRes
loop(n-1,currRes*n) //把最后要做计算的*n放在了另一个参数 保存在当前乘积计算结果上面
//在栈帧里面覆盖
}
loop(n,currRes = 1)
}
}
package chapter05
object Test11_ControlAbstraction {
def main(args: Array[String]): Unit = {
//1.传值参数
def f0(a:Int):Unit={
println("a:"+a)
println("a:"+a)
}
f0(23)
def f1():Int={
println("f1调用")
12
}
f0(f1())
println("-----------------------------------")
//2.传名参数 传递的不再是具体的值,而是一部分代码块
def f2(a: =>Int):Unit={
println("a:"+a)
println("a:"+a)
}
f2(23)
println("-------------------------------------")
f2(f1()) //这里并不是调用几次 执行几次 是要看传名参数的代码块
//控制抽象 传名参数的代码块 赋给了a a执行几次 f1就会被调用几次
println("--------------------------------")
f2({
println("这是一个代码块")
29
})
}
}
package chapter05
object Test12_MyWhile {
def main(args: Array[String]): Unit = {
var n =10
//1.常规的while循环
while(n>=1) {
println(n)
n -= 1
}
//2.用闭包实现一个函数,将代码块作为参数传入,递归调用
def myWhile(condition: =>Boolean):(=>Unit)=>Unit ={
//内层函数需要递归调用,参数就是循环体
def doLoop(op: =>Unit):Unit={
if(condition){
op
myWhile(condition)(op)
}
}
doLoop _
}
n=10
myWhile((n>=1))({
println(n)
n-=1
})
//3.用匿名函数实现
def myWhile2(condition: =>Boolean):(=>Unit)=>Unit ={
//内层函数需要递归调用,参数就是循环体
op =>{
if(condition){
op
myWhile2(condition)(op)
}
}
}
println("-------------------------------")
n=10
myWhile((n>=1)){
println(n)
n-=1
}
//4.用柯里化实现
def myWhile3(condition: =>Boolean)(op :Unit):Unit = {
if (condition) {
op
myWhile2(condition)(op)
}
}
println("-------------------------------")
n=10
myWhile((n>=1)){
println(n)
n-=1
}
}
}
package chapter05
//惰性求值
object Test13_Lazy {
def main(args: Array[String]): Unit = {
lazy val result:Int = sum(13,47)
println("1,函数调用")
println("2,result="+result)
println("4,result="+result) //已经计算出来 不需要再次计算
}
def sum(a: Int, b: Int):Int={
println("3,sum调用")
a+b
}
}
|