結合例項學習F#(一) --快速入門
2 let container = Array.create (n+1) 0
3 let rec loop acc = function
4 |[] -> List.rev acc
5 |hd::tl ->
6 if container.[hd] =1 then
7 loop acc tl
8 else
9 for j in [hd .. hd .. n] do
10 container.[j] 1
11 loop (hd::acc) tl
12 loop [] [2 .. n]
13
14 let primesBefore120 = GetAllPrimesBefore 120
廢話少說,直接進入正題吧
第一行,申明函式GetAllPrimesBefore, 並且該函式有一個引數n, 在這裡我沒有指定n的型別,因為編繹器可以通過函式體對n的型別進去推斷,比如在本例中,n就是int型別,當然我們也可以顯示的指定n的型別,比如 let GetAllPrimesBefore (n:int),這樣我們就指定了n為int型 (注意:(n:int)中的括號不能省略,let GetAllPrimesBefore n : int 的意思是該函式返回的值的int型)。說完了引數,再說下返回值,同樣,編繹器會根據函式體上下文對返回值型別進去推斷,所以我們不需要申明返回型別。
第二行,首先請注意該行與第一行相對有一個縮排({TAB}),F#和Python一樣,也是通過{TAB}縮排來組織程式碼結構的。這一行我們定義了一個變數container,它的型別是Array,大小為 n+1, 並且值全部初使化為0
2 |[] -> List.rev acc
3 |hd::tl ->
4 if container.[hd] =1 then
5 loop acc tl
6 else
7 for j in [hd .. hd .. n] do
8 container.[j] 1
9 loop (hd::acc) tl
接下來就是這個函式的主要部分了(原程式中的3-11行),首先我們定義了一個遞迴函式(我們發現定義遞迴函式需要加rec關鍵字)。它接受兩個引數,acc和一個List,有朋友可能要問了,這裡明明我只看到一個引數acc,你說的那個List在哪呢?可能有細心的朋友也發現了這裡的函式定義不光前面有rec,在等號後面還加了個function,那麼function是做什麼用的呢?
這裡我需要首先講一下Pattern Matching, Pattern Matching有些類似於C#中的switch語句(當然它要比C#中的switch強大許多,但這不是本文的目地,所以略去不表),可以根據expr的值去執行某一具體分支,它的基本語法也很簡單,我們還是結合一個具體例項來看一下(例子比較簡單,只是為了說明問題)。 這個例子大家很容易看懂吧,我就不詳細解釋了,只是說明一點,'_'用來匹配所有別的情況。
match laguageInUse with
| "C#" -> printfn "Hello, C# developer!"
| "F#" -> printfn "Hello, F# developer!"
|_ -> printfn "Hello, other developers!"
因為Pattern Matching在F#中的使用範圍實在太廣了,所以就引入了一種簡化版,這就是上面大家看到的等號後面的function的作用,我們可以把上面的例子簡化成
| "C#" -> printfn "Hello, C# developer!"
| "F#" -> printfn "Hello, F# developer!"
|_ -> printfn "Hello, other developers!"
怎麼樣?既少了給引數起名的煩惱,也少敲不少字吧,嘿嘿。
接下來我再簡單介紹下F#中非常重要的一個基本型別List, 其基本表示形式為 [ item1;item2; .. ;itemn]
F#中List是immutable型別,我們只能訪問裡面的值,不能改動裡面的值,任何改動List的需求只能通過構建新的List來實現。稍一思考,大家就會很快發現要實現一個高效的immutable list, 那最簡單的就是對其頭結點進去操作了(插入和刪除都可以達到O(1),當然插入和刪除會構建一個新的List,原List不會改變),F#中的List也是基於這種形式,所有的List都可以看成是Head+Tail(除了Head外的所有結點),F#提供了相應的庫函式List.hd, List.tl,並且提供了:: (cons operator)來幫助我們方便的構建一個List,比如1::2::[]就表示List [1;2] (注意1和2之間我用的是;不是, 如果寫成[1,2],那個表示該List只有一個元素 (1,2),至於(1,2)是什麼型別,為了使文章儘量緊湊,我們今天就不講了)
有了上面這些知識,再看本文一開始的函式就簡單多了
|[] -> List.rev acc
|hd::tl ->
if container.[hd] =1 then
loop acc tl
else
for j in [hd .. hd .. n] do
container.[j] 1
loop (hd::acc) tl
首先,該函式的第二個引數是List,
當List為空時,就把acc反序返回,
當List不為空時,把List分成兩部分(hd::tl),檢查噹噹前值n (n的值等於td) 是否己被標記
如果己經被標記(container.[hd] =1),略過當前值,檢查接下來的值 loop acc tl
如果沒有被標記(當前值是素數),用當前值和acc構建一個新List (hd::acc),並對當前值的所有倍數進去標記(for loop),然後檢查下一個值 loop (hd::acc) tl
這裡有兩點需要特別說明一下:
1. container是一個Array型別的引數,Array在F#中是mutable型別的容器,我們可以修改裡面的元素,訪問元素用Array.[i], 修改元素用Array. 2. for loop的基本形式為 for
看完了內部函式,我們再接著往下看(原程式第12行)
這裡就很簡單了,呼叫我們剛剛定義的內部函式,(acc為空List [], 第二個引數為List [2 .. n]),其返回值(List acc)就是函式GetAllPrimesBefore的返回值,F#中函式有返回值時不需要敲return.
函式呼叫也很簡單,(不需要在引數與函式名之間加括號)
後記
1. F#中函式體內可以定義新的值,變數和函式。(只在當前函式體內可見)。當然,這樣做的好處顯而易見,我就不囉嗦了。
2. Recursive function是functional programming中很常用的一種演算法實現方式。functional programming language往往會針對尾遞迴進行特別的優化,F#也不例外,所以我們需要儘可能的把遞迴寫成尾遞迴的形式,這個有時就需要像本文一樣藉助accumulator來實現。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-612011/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 結合例項學習|字元編碼和解碼字元
- react-dva學習 --- 用例項來入門React
- 深度學習快速入門3本書組合深度學習
- 【深度學習】--DCGAN從入門到例項應用深度學習
- SoapUI入門例項UI
- TypeScript入門例項TypeScript
- Websocet 入門例項Web
- Flutter 入門例項Flutter
- Vue入門指南-01建立vue例項 (快速上手vue)Vue
- Android外掛化快速入門與例項解析(VirtualApk)AndroidAPK
- 抽象結合例項 Employee抽象
- Maven例項講解教程,從零開始學Maven,帶你快速入門!Maven
- 【深度學習篇】---CNN和RNN結合與對比,例項講解深度學習CNNRNN
- 機器學習PAI快速入門機器學習AI
- 【SpringBoot學習一】開發入門--快速建立springboot程式Spring Boot
- vue 快速入門 系列 —— 例項方法(或 property)和靜態方法Vue
- vue 快速入門 系列 —— Vue 例項的初始化過程Vue
- Web Components 入門例項教程Web
- Vue專案入門例項Vue
- opengl簡單入門例項
- Django+MySQL 例項入門DjangoMySql
- Makefile例項學習
- vue入門筆記體系(一)vue例項Vue筆記
- 【TVM 學習資料】TensorIR 快速入門
- 【MongoDB學習筆記】MongoDB 快速入門MongoDB筆記
- 前端學習 node 快速入門 系列 —— npm前端NPM
- JavaScript學習筆記1—快速入門JavaScript筆記
- Vue入門指南-05 Vue例項的生命週期(快速上手vue)Vue
- 如何快速的學習一項技術?
- MyBatis基於Maven入門例項MyBatisMaven
- Python——astroplan庫入門例項(二)PythonAST
- React 入門-寫個 TodoList 例項React
- 【Oracle】ASM例項安裝入門OracleASM
- Egg入門學習(一)
- leaflet學習一 入門
- unity2019 ECS入門例項:建立一個EntityUnity
- 24 個例項入門並掌握「Webpack4」(一)Web
- React入門例項參考阮一峰部落格React
- tail命令學習例項AI