《Scala編程基礎》課件-第4章 函數式編程_第1頁
《Scala編程基礎》課件-第4章 函數式編程_第2頁
《Scala編程基礎》課件-第4章 函數式編程_第3頁
《Scala編程基礎》課件-第4章 函數式編程_第4頁
《Scala編程基礎》課件-第4章 函數式編程_第5頁
已閱讀5頁,還剩48頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1.函數概述幾個概念的說明在學習Scala中將方法、函數、函數式編程和面向對象編程明確一下:1.在scala中,方法和函數幾乎可以等同(比如他們的定義、使用、運行機制都一樣的),只是函數的使用方式更加的靈活多樣。函數式編程介紹2.函數式編程是從編程方式(范式)的角度來談的,可以這樣理解:函數式編程把函數當做一等公民,支持的函數的多種使用方式。

比如:在Scala當中,函數是一等公民,像變量一樣,既可以作為函數的參數使用,也可以將函數賦值給一個變量.,函數的創建不用依賴于類或者對象,而在Java當中,函數的創建則要依賴于類、抽象類或者接口。3.面向對象編程是以對象為基礎的編程方式。4.在scala中函數式編程和面向對象編程融合在一起了。函數式編程介紹"函數式編程"是一種"編程范式"(programmingparadigm)。它屬于"結構化編程"的一種,主要思想是把運算過程盡量寫成一系列嵌套的函數調用。函數式編程中,將函數也當做數據類型,因此可以接受函數當作輸入(參數)和輸出(返回值)。函數式編程中,最重要的就是函數。函數式編程介紹為完成某一功能的程序指令(語句)的集合,稱為函數。函數狹義的定義基本語法def函數名([參數名:參數類型],...)[[:返回值類型]

=]

{

語句...

return返回值}函數的格式函數聲明關鍵字為def

(definition)[參數名:參數類型],...:表示函數的輸入(就是參數列表),可以沒有。

如果有,多個參數使用逗號間隔函數中的語句:表示為了實現某一功能代碼塊函數可以有返回值,也可以沒有如果沒有return,默認以執行到最后一行的結果作為返回值函數的格式函數-調用過程在Scala中,函數的調用過程非常簡單。要調用一個函數,只需使用函數名和實際參數列表,并用圓括號括起來。為了讓大家更好的理解函數調用機制,比如一下例子,getSum計算兩個數的和,并返回結果。

objectTest01{defmain(args:Array[String]):Unit={valn1=1valn2=3valres=getSum(n1,n2)println("res="+res)}defgetSum(n1:Int,n2:Int):Int={returnn1+n2}}函數-調用機制2.函數細節和注意事項1.函數的形參列表可以是多個,如果函數沒有形參,調用時可以不帶()2.形參列表和返回值列表的數據類型可以是值類型和引用類型。3.Scala中的函數可以根據函數體最后一行代碼自行推斷函數返回值類型。那么在這種情況下,return關鍵字可以省略3.defgetSum(n1:Int,n2:Int):Int={n1+n2}4.defgetSum(n1:Int,n2:Int)={n1+n2}函數注意事項和細節討論4.因為Scala可以自行推斷,所以在省略return關鍵字的場合,返回值類型也可以省略5.如果函數明確使用return關鍵字,那么函數返回就不能使用自行推斷了,這時要明確寫成:返回類型=,當然如果你什么都不寫,即使有return返回值為()defgetSum(n1:Int,n2:Int):Int={//因為這里有明確的return,這時getSum就不能省略:Int=的Int了

returnn1+n2}函數注意事項和細節討論6.如果函數明確聲明無返回值(聲明Unit),那么函數體中即使使用return關鍵字也不會有返回值7.如果明確函數無返回值或不確定返回值類型,那么返回值類型可以省略(或聲明為Any)8.Scala語法中任何的語法結構都可以嵌套其他語法結構(靈活),即:函數中可以再聲明/定義函數,類中可以再聲明類,方法中可以再聲明/定義方法函數注意事項和細節討論9.Scala函數的形參,在聲明參數時,直接賦初始值(默認值),這時調用函數時,如果沒有指定實參,則會使用默認值。如果指定了實參,則實參會覆蓋默認值。objectHello01{defmain(args:Array[String]):Unit={println(sayOk())println(sayOk("venassa"))//覆蓋默認值

}defsayOk(name:String="jack"):String={returnname+"ok!"}}函數注意事項和細節討論10.如果函數存在多個參數,每一個參數都可以設定默認值,那么這個時候,傳遞的參數到底是覆蓋默認值,還是賦值給沒有默認值的參數,就不確定了(默認按照聲明順序[從左到右])。在這種情況下,可以采用帶名參數。通過指定參數的名字,我們可以明確指出要為哪個參數賦值,而不必遵循參數的聲明順序。例如:defformatName(first:String="John",last:String="Doe")=s"$first$last"println(formatName(last="Smith",first="Jane"))函數注意事項和細節討論11.Scala函數的形參默認是val的,因此不能在函數中進行修改。deftest(n:Int):Unit={n=n+1

//編譯錯誤(×)Reassignmenttoval}函數注意事項和細節討論12.遞歸函數未執行之前是無法推斷出來結果類型,在使用時必須有明確的返回值類型13.Scala函數支持可變參數說明:args是集合,通過for循環

可以訪問到各個值。可變參數需要寫在形參列表的最后。//支持0到多個參數defsum(args:Int*):Int={}//支持1到多個參數defsum(n1:Int,args:Int*):Int={}函數注意事項和細節討論3.遞歸函數定義:遞歸是指在一個函數的定義中直接或間接地調用該函數本身的行為。這種自我引用的能力讓遞歸成為解決某些類型問題的理想選擇,如樹形結構遍歷、數學運算(如階乘、斐波那契數列)等。遞歸的基本要素:基準情況(BaseCase):必須有一個或多個條件可以終止遞歸調用,否則會導致無限遞歸。遞歸步驟(RecursiveStep):每次遞歸調用都應使問題規模減小,逐漸接近基準情況。1.什么是遞歸?在Scala中,定義遞歸函數的方式與其他函數相似,但有一個重要區別:當函數是遞歸的時,必須顯式聲明返回值類型。這是因為編譯器無法在編譯前預測遞歸調用的結果類型。//定義一個計算階乘的遞歸函數deffactorial(n:Int):Int={if(n<=1)1//基準情況elsen*factorial(n-1)//遞歸步驟}上述factorial函數接受一個整數參數n,并根據n的值決定是返回1還是繼續遞歸調用自身。注意,這里我們明確指定了返回值類型為Int。2.Scala中的遞歸函數讓我們來看幾個使用遞歸函數的實際例子,以便更清楚地理解它們的工作原理。3.1計算階乘階乘是一個經典的遞歸案例。給定一個非負整數n,它的階乘表示為n!,定義為所有小于等于n的正整數的乘積。對于0和1,階乘定義為1。deffactorial(n:Int):Int={if(n==0||n==1)1elsen*factorial(n-1)}3.遞歸函數的例子3.2斐波那契數列斐波那契數列是以意大利數學家萊昂納多·斐波那契命名的一系列數字,其中每個數字是前兩個數字之和。序列從0和1開始,即0,1,1,2,3,5,8,13...deffibonacci(n:Int):Int={if(n<=1)nelsefibonacci(n-1)+fibonacci(n-2)}

println(fibonacci(7))//輸出:133.遞歸函數的例子在Scala中,尾遞歸是一種特殊的遞歸形式,它可以被編譯器優化成循環,從而避免棧溢出的風險。為了使一個遞歸函數被認為是尾遞歸,遞歸調用必須是函數體中的最后一個操作。//使用@tailrec注解確保編譯器檢查尾遞歸importscala.annotation.tailrec

deffactorialTailRec(n:Int,acc:Int=1):Int={if(n==0)accelsefactorialTailRec(n-1,n*acc)}在這個版本的factorialTailRec函數中,我們引入了一個額外的參數acc作為累加器,用來累積中間結果。由于遞歸調用是函數體的最后一行,因此它可以被優化成迭代。4.尾遞歸優化通過本節課,我們了解了Scala中遞歸函數的概念及其應用。遞歸為我們提供了一種優雅的方法來解決那些可以通過分治法簡化的問題。同時,我們也學習了如何利用尾遞歸優化來提高性能,并防止潛在的棧溢出問題。5.總結4.高階函數在Scala中,高階函數(Higher-orderFunction,HOF)是指可以:接收函數作為參數,或者返回一個函數。這意味著高階函數的參數或返回值可以是其他函數,使得函數的靈活性和表達能力得到增強。1.高階函數的定義Scala支持一等函數,即函數可以作為值來傳遞。這使得函數不僅僅是代碼的執行指令,還可以作為數據在程序中流動。高階函數通常具有以下兩個特性:函數作為參數:高階函數接收另一個函數作為參數,來對數據進行處理或轉換。函數作為返回值:高階函數返回一個函數,可以創建新的函數并返回,甚至基于運行時的情況動態創建函數。2.高階函數的基本特性3.1函數作為參數一個常見的高階函數是map。map方法接收一個函數作為參數,并對集合中的每個元素應用該函數,返回新的集合。

代碼說明:1.numbers.map(x=>x*x):這里,map方法接收了一個匿名函數x=>x*x作為參數,這個函數對每個元素進行平方操作。2.map函數返回一個新的集合,其中每個元素都是原集合元素的平方。objectHigherOrderFunctionExample{defmain(args:Array[String]):Unit={valnumbers=List(1,2,3,4,5)//map函數接收一個函數參數,返回新集合valsquaredNumbers=numbers.map(x=>x*x)println(squaredNumbers)//輸出:List(1,4,9,16,25)}}3.高階函數的示例3.2函數作為返回值高階函數還可以返回函數。以下示例展示了如何創建一個返回函數的函數:objectHigherOrderFunctionReturnExample{defmultiplyBy(factor:Int):Int=>Int={//返回一個新的函數(x:Int)=>x*factor}

defmain(args:Array[String]):Unit={valmultiplyByTwo=multiplyBy(2)//創建一個返回乘以2的函數valmultiplyByThree=multiplyBy(3)//創建一個返回乘以3的函數

println(multiplyByTwo(5))//輸出:10println(multiplyByThree(5))//輸出:15}}代碼說明:1.multiplyBy(factor:Int)是一個高階函數,它返回一個新的函數(x:Int)=>x*factor,該函數將輸入的x乘以factor。2.在main方法中,通過multiplyBy(2)和multiplyBy(3)創建了兩個不同的函數multiplyByTwo和multiplyByThree,分別用于將輸入數乘以2和3。3.高階函數的示例在Scala的標準庫中,很多方法都可以看作是高階函數,特別是在集合操作中。以下是幾個常見的高階函數:4.1filterfilter方法接收一個函數(通常是一個判斷條件)作為參數,返回一個新的集合,包含那些滿足條件的元素。valnumbers=List(1,2,3,4,5,6)valevenNumbers=numbers.filter(x=>x%2==0)println(evenNumbers)//輸出:List(2,4,6)4.常見的高階函數4.2reducereduce方法接收一個二元操作函數(通常是一個合并函數),通過將函數應用于集合中的所有元素,最終返回一個單一的結果。valnumbers=List(1,2,3,4,5)valsumWithInitialValue=numbers.fold(10)((x,y)=>x+y)println(sumWithInitialValue)//輸出:254.常見的高階函數高階函數在實際應用中非常有用,尤其在以下場景中表現得尤為突出:集合處理:如map、filter、reduce、fold等函數可以使得集合操作更加簡潔、優雅。函數式編程:Scala是支持函數式編程的語言,高階函數使得函數式編程風格更加自然和靈活。回調函數:許多API和框架使用高階函數來實現回調機制。例如,處理異步任務時,我們常常會傳入一個回調函數。動態函數生成:通過高階函數,可以動態地創建特定的計算邏輯,提供更高的抽象和靈活性。5.高階函數的應用場景高階函數是Scala的一個重要特性,它允許函數作為參數傳遞,也可以返回函數。通過高階函數,開發者可以寫出更簡潔、模塊化和高效的代碼。理解并掌握高階函數的使用,對深入學習Scala及函數式編程至關重要。通過上面的示例,我們了解了如何在Scala中使用高階函數進行集合操作、動態函數生成等。Scala的高階函數使得代碼更加簡潔且表達能力強大,尤其在函數式編程中發揮了巨大的作用。6.小結5.匿名函數匿名函數(AnonymousFunction),也稱為Lambda函數,是一種沒有名稱的函數。它通常用于簡化代碼,尤其是在需要傳遞函數作為參數的場景中。Scala中匿名函數的基本形式如下:(parameters)=>expression?parameters:函數的輸入參數。?=>:分隔符,表示函數參數與函數體之間的關系。?expression:函數體,表示計算結果。1.匿名函數的定義?簡潔性:匿名函數無需定義顯式的函數名,常用于簡短的邏輯。?可傳遞性:匿名函數可以作為參數傳遞給其他函數,使得代碼更具靈活性。?函數式編程:匿名函數是函數式編程中的一種重要工具,常用于高階函數和集合操作中。2.匿名函數的特點3.1示例:簡單的匿名函數匿名函數的基本語法格式如下:(parameters)=>expressionobjectAnonymousFunctionExample{defmain(args:Array[String]):Unit={valadd=(x:Int,y:Int)=>x+y//定義一個匿名加法函數println(add(5,3))//輸出:8}}代碼說明:1.(x:Int,y:Int)=>x+y:這行代碼定義了一個接受兩個Int類型參數并返回它們和的匿名函數。2.valadd=:將該匿名函數賦值給一個變量add,并通過add(5,3)調用它,計算并輸出5+3=8。3.匿名函數的基本語法4.1用作集合操作中的函數匿名函數經常與集合操作(如map、filter、reduce等)一起使用。Scala提供了許多高階函數,這些函數通常接收匿名函數作為參數。valnumbers=List(1,2,3,4,5)valsquaredNumbers=numbers.map(x=>x*x)//使用匿名函數進行平方操作println(squaredNumbers)//輸出:List(1,4,9,16,25)代碼說明:1.numbers.map(x=>x*x):對numbers列表中的每個元素應用匿名函數x=>x*x,即將每個元素平方。2.返回一個新列表List(1,4,9,16,25)。4.匿名函數的常見用途4.2用作filter函數filter函數用于篩選集合中符合條件的元素,匿名函數可以用來定義篩選條件。valnumbers=List(1,2,3,4,5,6)valevenNumbers=numbers.filter(x=>x%2==0)//使用匿名函數篩選偶數println(evenNumbers)//輸出:List(2,4,6)代碼說明:1.numbers.filter(x=>x%2==0):使用匿名函數x=>x%2==0來篩選出偶數。2.返回一個新列表List(2,4,6)。4.匿名函數的常見用途4.3用作reduce函數reduce函數用于將集合中的元素通過某種方式合并,通常接收一個二元操作函數。我們也可以使用匿名函數作為操作符。代碼說明:1.numbers.reduce((x,y)=>x+y):使用匿名函數(x,y)=>x+y將列表中的所有元素相加。2.返回結果15,即1+2+3+4+5=15。valnumbers=List(1,2,3,4,5)valsum=numbers.reduce((x,y)=>x+y)//使用匿名函數進行加法操作println(sum)//輸出:154.匿名函數的常見用途在Scala中,匿名函數的參數類型通常可以由編譯器推導出來,這使得匿名函數的書寫更加簡潔。5.1示例:類型推導valmultiply=(x:Int,y:Int)=>x*y//類型可以被推導println(multiply(3,4))//輸出:125.類型推導與簡化5.2示例:簡化的匿名函數如果匿名函數的參數類型和返回類型是清晰的,甚至可以省略類型聲明。valadd=(x:Int,y:Int)=>x+y//完整的聲明valsubtract=(_:Int,_:Int)=>0//也可以省略參數名稱代碼說明:?在第二個例子中,(_:Int,_:Int)表示忽略參數名稱,只提供參數類型,適用于簡單的占位符。5.類型推導與簡化匿名函數是Scala語言中非常有用的特性之一。通過匿名函數,我們可以更加簡潔地編寫代碼,尤其在傳遞函數作為參數時,它極大地提升了代碼的靈活性和可讀性。匿名函數廣泛應用于高階函數、集合操作、回調函數等場景,是函數式編程的重要組成部分。以上就是關于Scala匿名函數的基礎要點。匿名函數不僅讓代碼更加簡潔,也為函數式編程提供了強大的支持。在實際開發中,掌握匿名函數的使用方法將幫助你更好地處理函數作為參數傳遞、集合操作以及動態生成函數等問題。6.小結6.列表Scala提供了多種集合類型來處理一系列元素,其中List和ListBuffer是兩種常見的列表實現。List是一個不可變的鏈表結構,而ListBuffer則是一個可變的緩沖區,允許在運行時動態地添加或移除元素。本文將詳細介紹這兩種列表的基礎概念、主要區別以及常用的操作方法,并通過代碼示例幫助理解。List是Scala中最常用的不可變集合之一,它是一個有序集合,可以存儲多個相同類型的元素。List在Scala中屬于不可變集合,這意味著一旦創建就不能修改,而是通過返回新的列表來進行變更。1.

List1.1List的定義與創建在Scala中,List可以通過伴生對象的apply方法創建,支持直接傳遞元素進行初始化。1.

ListobjectListExample{defmain(args:Array[String]):Unit={//創建一個包含元素的Listvallist=List(1,2,3,4,5)

//創建一個空ListvalemptyList=List.empty[Int]

//訪問List的元素println(list(0))//輸出:1

//遍歷Listlist.foreach(println)//逐行輸出1,2,3,4,5}}代碼說明:1.List(1,2,3,4,5)創建了一個包含5個元素的整數列表。2.List.empty[Int]創建了一個空的整數列表。3.list(0)訪問列表中的第一個元素,foreach方法遍歷列表,逐個打印元素。1.2List的常見操作objectListOperations{defmain(args:Array[String]):Unit={vallist=List(1,2,3,4,5)

//取出頭元素和尾元素println(list.head)//輸出:1println(list.tail)//輸出:List(2,3,4,5)

//拼接列表valnewList=list:+6//在末尾添加元素println(newList)//輸出:List(1,2,3,4,5,6)

valprependedList=0+:list//在頭部添加元素println(prependedList)//輸出:List(0,1,2,3,4,5)

//反轉列表println(list.reverse)//輸出:List(5,4,3,2,1)

//映射操作valsquaredList=list.map(x=>x*x)println(squaredList)//輸出:List(1,4,9,16,25)}}代碼說明:1.head方法返回列表的第一個元素,tail返回除第一個元素外的所有元素。2.:+在列表末尾添加元素,+:在列表頭部添加元素。3.reverse反轉列表。4.map對列表中的每個元素進行映射操作。1.

ListListBuffer是Scala集合庫中的可變列表,位于scala.collection.mutable包中。與List不同,ListBuffer可以動態修改元素,支持添加和刪除操作。ListBuffer在修改后不會返回新的列表,而是直接修改原列表。2.1ListBuffer的定義與創建在使用ListBuffer前,需要導入scala.collection.mutable.ListBuffer。2.可變列表(ListBuffer)importscala.collection.mutable.ListBufferobjectListBufferExample{defmain(args:Array[String]):Unit={//創建一個ListBuffervalbuffer=ListBuffer(1,2,3,4,5)

//添加元素buffer+=6println(buffer)//輸出:ListBuffer(1,2,3,4,5,6)

//刪除元素buffer-=2println(buffer)//輸出:ListBuffer(1,3,4,5,6)

//訪問元素println(buffer(0))//輸出:1}}代碼說明:1.ListBuffer(1,2,3,4,5)創建了一個包含5個元素的可變列表。2.+=用于在列表末尾添加元素,-=刪除指定元素。3.通過索引訪問元素,如buffer(0)訪問第一個元素。2.可變列表(ListBuffer)2.2ListBuffer的常見操作importscala.collection.mutable.ListBuffer

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論