柚子快報激活碼778899分享:開發(fā)語言 后端 Scala函數(shù)
柚子快報激活碼778899分享:開發(fā)語言 后端 Scala函數(shù)
day03 Scala函數(shù)
一、創(chuàng)建函數(shù)
package day01
?
object Functions {
def main(args: Array[String]): Unit = {
? //val maxF = max _的意思是將max函數(shù)賦值給名為maxF的變量,
? //但是在這里max后面添加了一個下劃線 _,表示將函數(shù)的類型轉(zhuǎn)換為函數(shù)值的類型
? val maxFunc = max _
? println(maxFunc(1, 2))
? println(fac(6))
? println(getIndex(Array[Int](1, 2, 3, 4), 3))
?
}
?
/*1、兩個值找最大值*/
def max(a:Int,b:Int):Int = {
? if(a > b) a else b
}
?
/*2、取絕對值*/
def abs(a:Int):Int = {
? // -a中的-表示前綴操作符
? if(a < 0) -a else a
}
?
/*3、找目標(biāo)值在數(shù)組中的下標(biāo)位置*/
def getIndex(arr:Array[Int],tar:Int):Int={
? // 也是用遞歸,循環(huán)找數(shù)組中的值,index是數(shù)組下表
? def loop(index:Int):Int={
? ? // 調(diào)用loop時,將index設(shè)為0,1、從第一個數(shù)查,如果相等返回當(dāng)前下標(biāo)
? ? // 2、如果不相等,index+1作為loop參數(shù),繼續(xù)調(diào)用loop
? ? // 3、直到數(shù)組下標(biāo)超過數(shù)組長度,返回-1
? ? if (index >= arr.length){
? ? ? -1
? ? ? // arr(index)表示當(dāng)前下標(biāo)的元素值
? ? }else if (arr(index) == tar){
? ? ? index
? ? }else {
? ? ? // 繼續(xù)查找對比
? ? ? loop(index+1)
? ? }
? }
? loop(0)
}
?
/*4、階乘,使用遞歸(自己調(diào)自己)*/
def fac(a:Int):Int = {
? // 遞歸:自己調(diào)自己
? // acc表示結(jié)果集
? def loop(n:Int,acc:Int):Int={
? ? if(n ==1) acc
? ? ? // 繼續(xù)調(diào)用loop,形成了循環(huán),當(dāng)n減到1,直接輸出結(jié)果
? ? ? // 先輸入(5,1)loop(5,1)==>loop(4,5)==>loop(3,20)==>loop(2,60)==>loop(1,120)
? ? else loop(n-1,acc*n)
? }
? loop(a,1)
}
/*階乘的另一個方法*/
def fac1(a:Int):Int={
? if (a ==1 ) 1 else fac1(a-1)*a
}
?
?
def formatAbs(num: Int): Unit = {
? val msg: String = "source data = %d,abs(num)=%d"
? println(msg.format(num, abs(num)))
}
def formatMax(num:Int,num2:Int):Unit={
? val msg: String="source data = %d,%d,max(num)=%d"
? println(msg.format(num,num2,max(num,num2)))
}
}
二、高階函數(shù)--泛化函數(shù)
當(dāng)一個函數(shù)被多次調(diào)用時,我們可以將這個函數(shù)寫成泛化函數(shù)
/*
* 參數(shù)列表:1、num:Int表示輸入的數(shù)字
* 2、funcName:String一個字符串
* 3、funct:Int=>Int 定義一個方法,輸入int類型,輸出int類型,方法名為funct
* ? funct表示自定義的方法名,
* ? Int表示輸入的參數(shù)類型,
* ? =>表示執(zhí)行函數(shù),
* ? Int表示執(zhí)行完函數(shù)返回的數(shù)據(jù)類型
*
*/
def format(num: Int, funcName: String, funct: Int => Int): Unit = {
? // %s表示字符串占位符
? val msg = "use %s conver %d to %d"
? println(msg.format(funcName, num, funct(num)))//use max conver -2 to 2
}
案例
package day01
?
object Functions {
def main(args: Array[String]): Unit = {
? //val maxF = max _的意思是將max函數(shù)賦值給名為maxF的變量,
? //但是在這里max后面添加了一個下劃線 _,表示將函數(shù)的類型轉(zhuǎn)換為函數(shù)值的類型
? val maxFunc = max _
? println(maxFunc(1, 2))
? println(fac(6))
? println(getIndex(Array[Int](1, 2, 3, 4), 3))
?
? println("========================泛化函數(shù)轉(zhuǎn)換============================")
?
? format(5,"fac函數(shù)",fac)
? format1(-3,abs)
? format2(3,2,"max",max)
}
?
/*1、兩個值找最大值*/
def max(a:Int,b:Int):Int = {
? if(a > b) a else b
}
?
/*2、取絕對值*/
def abs(a:Int):Int = {
? // -a中的-表示前綴操作符
? if(a < 0) -a else a
}
?
/*3、找目標(biāo)值在數(shù)組中的下標(biāo)位置*/
def getIndex(arr:Array[Int],tar:Int):Int={
? // 也是用遞歸,循環(huán)找數(shù)組中的值,index是數(shù)組下表
? def loop(index:Int):Int={
? ? // 調(diào)用loop時,將index設(shè)為0,1、從第一個數(shù)查,如果相等返回當(dāng)前下標(biāo)
? ? // 2、如果不相等,index+1作為loop參數(shù),繼續(xù)調(diào)用loop
? ? // 3、直到數(shù)組下標(biāo)超過數(shù)組長度,返回-1
? ? if (index >= arr.length){
? ? ? -1
? ? ? // arr(index)表示當(dāng)前下標(biāo)的元素值
? ? }else if (arr(index) == tar){
? ? ? index
? ? }else {
? ? ? // 繼續(xù)查找對比
? ? ? loop(index+1)
? ? }
? }
? loop(0)
}
?
/*4、階乘,使用遞歸(自己調(diào)自己)*/
def fac(a:Int):Int = {
? // 遞歸:自己調(diào)自己
? // acc表示結(jié)果集
? def loop(n:Int,acc:Int):Int={
? ? if(n ==1) acc
? ? ? // 繼續(xù)調(diào)用loop,形成了循環(huán),當(dāng)n減到1,直接輸出結(jié)果
? ? ? // 先輸入(5,1)loop(5,1)==>loop(4,5)==>loop(3,20)==>loop(2,60)==>loop(1,120)
? ? else loop(n-1,acc*n)
? }
? loop(a,1)
}
/*階乘的另一個方法*/
def fac1(a:Int):Int={
? if (a ==1 ) 1 else fac1(a-1)*a
}
?
def form():Unit={println("=====================格式轉(zhuǎn)換=======================")}
?
def formatAbs(num: Int): Unit = {
? val msg: String = "source data = %d,abs(num)=%d"
? println(msg.format(num, abs(num)))
}
def formatMax(num:Int,num2:Int):Unit={
? val msg: String="source data = %d,%d,max(num)=%d"
? println(msg.format(num,num2,max(num,num2)))
}
?
def form1():Unit={println("=====================泛化函數(shù):公共的轉(zhuǎn)換=======================")}
?
/*
* 參數(shù)列表:1、num:Int表示輸入的數(shù)字
* 2、funcName:String一個字符串
* 3、funct:Int=>Int 定義一個方法,輸入int類型,輸出int類型,方法名為funct
* ? funct表示自定義的方法名,
* ? Int表示輸入的參數(shù)類型,
* ? =>表示執(zhí)行函數(shù),
* ? Int表示執(zhí)行完函數(shù)返回的數(shù)據(jù)類型
*
*/
def format(num: Int, funcName: String, funct: Int => Int): Unit = {
? // %s表示字符串占位符
? val msg = "use %s conver %d to %d"
? println(msg.format(funcName, num, funct(num)))//use max conver -2 to 2
}
?
/**/
def format1(num: Int, fun: Int => Int): Unit = {
? val msg = "use function conver %d to %d"
? println(msg.format(num, fun(num)))
}
?
/*兩個參數(shù)的格式化*/
def format2(num:Int,num2:Int,functioin:String,fun:(Int,Int)=>Int):Unit={
? val msg="%d,%d使用%s函數(shù)得出的結(jié)果為:%d"
? println(msg.format(num, num2, functioin,fun(num, num2)))
}
}
三、高階函數(shù)--多態(tài)函數(shù)(泛型函數(shù))
把針對單個類型的函數(shù)運(yùn)用到可以針對多個類型,函數(shù)名后面加上泛型[A]
1、正常的函數(shù)形式
package day01
?
object MultiMode {
// 正常模式,判斷數(shù)組中是否含有目標(biāo)值
def arrayContain(arr:Array[Int],tar:Int):Boolean={
? def loop(index:Int):Boolean={
? ? if (index >= arr.length){
? ? ? false
? ? }else if (arr(index) == tar){
? ? ? true
? ? }else{
? ? ? loop(index +1)
? ? }
? }
? // 使用loop函數(shù),從索引0開始
? loop(0)
}
?
def main(args: Array[String]): Unit = {
? println(arrayContain(Array[Int](1,2, 3, 4, 5), 5))
}
}
?
2、多態(tài)函數(shù)
相當(dāng)于寫一個模板,里面的類型用A表示,A可以是任何參數(shù)
案例1:判斷一個值是否存在數(shù)組中
/*
* 兩個參數(shù):一個數(shù)組和一個函數(shù)
* 1、數(shù)組中元素類型在調(diào)用時可以定義
* 2、函數(shù)參數(shù)func:(A=>Boolean):表示這個形參func函數(shù)是輸入一個A類型的數(shù),返回Boolean類型的值
* 但是具體怎么執(zhí)行,等調(diào)用這個函數(shù)時,用具體的執(zhí)行方式來替換這個形參
* */
def arrayMulti[A](arr:Array[A],func:A=>Boolean):Boolean={
? def loop(index:Int):Boolean={
? ? if (index >= arr.length){
? ? ? false
? ? ? // 表示調(diào)用這個形參返回的Boolean值,具體是什么執(zhí)行方法,在調(diào)用時寫出來,但不管怎么寫,arr(index)就是寫的函數(shù)形參的參數(shù)
? ? }else if (func(arr(index))){
? ? ? true
? ? }else{
? ? ? loop(index +1)
? ? }
? }
? // 使用loop函數(shù),從索引0開始
? loop(0)
}
?
def main(args: Array[String]): Unit = {
? /*第二個參數(shù)應(yīng)該是一個函數(shù)
? def func(x:Int):Boolean={
? if (x == 5) true
? else false
? }
? 這個func咱們簡寫了,func在loop函數(shù)被多次循環(huán)調(diào)用時,參數(shù)x就是arr(index)
? ? */
? // (x: Int) => x == 5
? println(arrayMulti(Array[Int](1, 2, 3, 4), (x: Int) => x == 5))
? println(arrayMulti(Array[String]("a", "b", "c"), (x: String) => x.equals("b")))
}
案例2:判斷一個數(shù)組是否是升序(或降序)排列
package day01
?
object MultiMode {
?
/*多態(tài)函數(shù)
* 判斷這個數(shù)組是否是升序(后降序)排列
* */
def multi[A](ar:Array[A],func:(A,A)=>Boolean):Boolean={
? /*
? 邏輯:從索引0開始,0>= 4,false,不返回true,繼續(xù)向下1<2,正確,但是前面加了!,所以還不返回,繼續(xù)執(zhí)行索引1
? 直到 6<5,錯誤,取反后為true,則返回false,結(jié)果就是false
? ? */
? def loop(index:Int):Boolean={
? ? ? //表示查到末尾還沒返回false,則整個數(shù)組就是正確的排序,中途有錯誤的,直接就返回false了,執(zhí)行不到這里了
? ? if (index >= ar.length -1) true
? ? ? // 順序正確,就取反讓其不返回false,繼續(xù)查找,直到順序不正確,取反if條件就成功執(zhí)行,返回了false
? ? else if (!func(ar(index),ar(index + 1))) false
? ? ? // 繼續(xù)查找
? ? else loop(index + 1)
? }
? loop(0)
}
?
def main(args: Array[String]): Unit = {
? println(multi[Int](Array[Int](1, 2, 3, 6, 5), (x: Int, y: Int) => x <= y))
}
}
返回值是函數(shù)的案例
def currying(x:Int,func:(Int,Int)=>Int):Int=>Int={
? // 返回值是個函數(shù)Int=>Int,所以要傳值一個Int類型的值,結(jié)果為Int類型(剛好func參數(shù)就是返回的Int值,所以借用func函數(shù))
? // (y:Int) => func(x,y)這個就是一個匿名函數(shù),符合返回一個函數(shù)的要求
? // 傳一個Int值
? (y:Int) => func(x,y)
}
?
/*
* 兩個參數(shù):1、一個A類型的數(shù)值
* 2、一個類型A和類型B生成一個類型C的函數(shù)
* 返回值:一個類型B生成一個類型C的函數(shù)
* 方法體:一個匿名函數(shù):傳一個類型B的值生成(由上面函數(shù)形參func生成的類型C數(shù)據(jù))類型C數(shù)據(jù)
* */
def currying1[A,B,C](a:A,func:(A,B)=>C):B=>C={
? (b:B)=>func(a,b)
}
?
?
def main(args: Array[String]): Unit = {
? // currying(2, (x: Int, y: Int) => x + y) 返回的這個表達(dá)式是函數(shù)
? val int_int = currying(2, (x: Int, y: Int) => x + y)
? println(int_int(4))//6
?
? val cur = currying1[Int,Int,String](5,(a:Int,b:Int)=> s"${a}$")
? println(cur(20))//520
}
四、柯里化函數(shù)(Currying)
將參數(shù)分開,每個參數(shù)都形成了一個函數(shù)
作用:協(xié)助編譯器進(jìn)行類型推斷
/*正常函數(shù)*/
def noCurry(x:Int,y:Int):Int={
? x + y
}
?
/*柯里化函數(shù)*/
def curry(x:Int)(y:Int):Int={
? x + y
}
?
def main(args: Array[String]): Unit = {
? println(noCurry(2, 3))
? println(curry(1)(3))
}
高階案例
/*
* 這個函數(shù)就是柯里化函數(shù)的證明過程
* 返回值就相當(dāng)于:A=>(B=>C),因為函數(shù)是偏右法則,所以()省略了
* A賦值1,B賦值2,流程就是:f(1)結(jié)果是一個函數(shù)(類型A生成)
* */
def curri[A,B,C](f:(A,B)=>C):A=> B=>C={
? ? ? // 相當(dāng)于(a:A)=>{(b:B)=> f(a,b)}
? (a:A)=> (b:B)=>f(a,b)
}
?
/*
* 這個函數(shù)就是柯里化函數(shù)的反證明過程
* */
def recurr[A,B,C](f:A=>B=>C):(A,B)=>C={
? (a:A,b:B)=> f(a)(b)
}
?
?
def main(args: Array[String]): Unit = {
? val func = curri[Int,Int,Int]((x:Int,y:Int)=> x+y)
? println(func)//是一個函數(shù)
? println(func(3))//也是一個函數(shù)
? println(func(3)(2))//5
}
案例
? def arrayMulti[A](arr: Array[A])(func: A => Boolean): Boolean = {
? def loop(index: Int): Boolean = {
? ? if (index >= arr.length) {
? ? ? false
? ? ? // 表示調(diào)用這個形參返回的Boolean值,具體是什么執(zhí)行方法,在調(diào)用時寫出來,但不管怎么寫,arr(index)就是寫的函數(shù)形參的參數(shù)
? ? } else if (func(arr(index))) {
? ? ? true
? ? } else {
? ? ? loop(index + 1)
? ? }
? }
? // 使用loop函數(shù),從索引0開始
? loop(0)
}
?
def main(args: Array[String]): Unit = {
?
? // 第二個參數(shù)本來應(yīng)該是(x:Int=> x == 5),
? // 因為是柯里化函數(shù),第二個參數(shù)的入?yún)㈩愋涂梢允÷粤?/p>
? println(arrayMulti(Array(2, 3, 4, 5, 7))(x => x == 5))
}
柚子快報激活碼778899分享:開發(fā)語言 后端 Scala函數(shù)
參考鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。