日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
F#入門:基本語法,模式匹配及List

F#隨著VSTS 2010 Beta1 發(fā)布也有一段時(shí)間了,園子里應(yīng)該也有不少人對它感興趣吧。下面的例子是我在學(xué)F# 基本語法時(shí)寫的一個(gè)簡單Sieve of Eratosthenes 實(shí)現(xiàn),通過剖析這一小段代碼,我希望大家能對F#有個(gè)簡單認(rèn)識,并能自己寫一些簡單的小程序。

做網(wǎng)站、網(wǎng)站設(shè)計(jì)的關(guān)注點(diǎn)不是能為您做些什么網(wǎng)站,而是怎么做網(wǎng)站,有沒有做好網(wǎng)站,給成都創(chuàng)新互聯(lián)公司一個(gè)展示的機(jī)會(huì)來證明自己,這并不會(huì)花費(fèi)您太多時(shí)間,或許會(huì)給您帶來新的靈感和驚喜。面向用戶友好,注重用戶體驗(yàn),一切以用戶為中心。

F#入門代碼

 
 
 
  1. let GetAllPrimesBefore n = 
  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

廢話少說,直接進(jìn)入正題吧

 
 
 
  1. let GetAllPrimesBefore n =

第一行,申明函數(shù)GetAllPrimesBefore, 并且該函數(shù)有一個(gè)參數(shù)n, 在這里我沒有指定n的類型,因?yàn)榫幚[器可以通過函數(shù)體對n的類型進(jìn)去推斷,比如在本例中,n就是int類型,當(dāng)然我們也可以顯示的指定n的類型,比如 let GetAllPrimesBefore (n:int),這樣我們就指定了n為int型 (注意:(n:int)中的括號不能省略,let GetAllPrimesBefore n : int 的意思是該函數(shù)返回的值的int型)。說完了參數(shù),再說下返回值,同樣,編繹器會(huì)根據(jù)函數(shù)體上下文對返回值類型進(jìn)去推斷,所以我們不需要申明返回類型。

 
 
 
  1. let container = Array.create (n+1) 0

第二行,首先請注意該行與第一行相對有一個(gè)縮進(jìn)({TAB}),F#和Python一樣,也是通過{TAB}縮進(jìn)來組織代碼結(jié)構(gòu)的。這一行我們定義了一個(gè)變量container,它的類型是Array,大小為 n+1, 并且值全部初使化為0

 
 
 
  1. let rec loop acc = function
  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 

接下來就是這個(gè)函數(shù)的主要部分了(原程序中的3-11行),首先我們定義了一個(gè)遞歸函數(shù)(我們發(fā)現(xiàn)定義遞歸函數(shù)需要加rec關(guān)鍵字)。它接受兩個(gè)參數(shù),acc和一個(gè)List,有朋友可能要問了,這里明明我只看到一個(gè)參數(shù)acc,你說的那個(gè)List在哪呢?可能有細(xì)心的朋友也發(fā)現(xiàn)了這里的函數(shù)定義不光前面有rec,在等號后面還加了個(gè)function,那么function是做什么用的呢?

 
 
 
  1. let rec loop acc = function

F#入門:模式匹配

這里我需要首先講一下Pattern Matching(模式匹配), Pattern Matching有些類似于C#中的switch語句(當(dāng)然它要比C#中的switch強(qiáng)大許多,但這不是本文的目地,所以略去不表),可以根據(jù)expr的值去執(zhí)行某一具體分支,它的基本語法也很簡單,我們還是結(jié)合一個(gè)具體實(shí)例來看一下(例子比較簡單,只是為了說明問題)。 這個(gè)例子大家很容易看懂吧,我就不詳細(xì)解釋了,只是說明一點(diǎn),'_'用來匹配所有別的情況。

 
 
 
  1. let ShowGreeting laguageInUse = 
  2.     match laguageInUse with
  3.     | "C#" -> printfn "Hello, C# developer!"
  4.     | "F#" -> printfn "Hello, F# developer!"
  5.     |_ -> printfn "Hello, other developers!"

因?yàn)镻attern Matching在F#中的使用范圍實(shí)在太廣了,所以就引入了一種簡化版,這就是上面大家看到的等號后面的function的作用,我們可以把上面的例子簡化成

 
 
 
  1. let ShowGreeting  = function    
  2.     | "C#" -> printfn "Hello, C# developer!"
  3.     | "F#" -> printfn "Hello, F# developer!"
  4.     |_ -> printfn "Hello, other developers!"

怎么樣?既少了給參數(shù)起名的煩惱,也少敲不少字吧,嘿嘿。

F#入門:List基本類型

接下來我再簡單介紹下F#中非常重要的一個(gè)基本類型List, 其基本表示形式為 [ item1;item2; .. ;itemn]

F#中List是immutable類型,我們只能訪問里面的值,不能改動(dòng)里面的值,任何改動(dòng)List的需求只能通過構(gòu)建新的List來實(shí)現(xiàn)。稍一思考,大家就會(huì)很快發(fā)現(xiàn)要實(shí)現(xiàn)一個(gè)高效的immutable list, 那最簡單的就是對其頭結(jié)點(diǎn)進(jìn)去操作了(插入和刪除都可以達(dá)到O(1),當(dāng)然插入和刪除會(huì)構(gòu)建一個(gè)新的List,原List不會(huì)改變),F(xiàn)#中的List也是基于這種形式,所有的List都可以看成是Head+Tail(除了Head外的所有結(jié)點(diǎn)),F#提供了相應(yīng)的庫函數(shù)List.hd, List.tl,并且提供了:: (cons operator)來幫助我們方便的構(gòu)建一個(gè)List,比如1::2::[]就表示List [1;2] (注意1和2之間我用的是;不是, 如果寫成[1,2],那個(gè)表示該List只有一個(gè)元素 (1,2),至于(1,2)是什么類型,為了使文章盡量緊湊,我們今天就不講了)

有了上面這些知識,再看本文一開始的函數(shù)就簡單多了

 
 
 
  1. let rec loop acc = function
  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  

首先,該函數(shù)的第二個(gè)參數(shù)是List,

      當(dāng)List為空時(shí),就把a(bǔ)cc反序返回,

      當(dāng)List不為空時(shí),把List分成兩部分(hd::tl),檢查當(dāng)當(dāng)前值n (n的值等于td) 是否己被標(biāo)記

            如果己經(jīng)被標(biāo)記(container.[hd] =1),略過當(dāng)前值,檢查接下來的值 loop acc tl

            如果沒有被標(biāo)記(當(dāng)前值是素?cái)?shù)),用當(dāng)前值和acc構(gòu)建一個(gè)新List (hd::acc),并對當(dāng)前值的所有倍數(shù)進(jìn)去標(biāo)記(for loop),然后檢查下一個(gè)值  loop (hd::acc) tl

這里有兩點(diǎn)需要特別說明一下:

      1. container是一個(gè)Array類型的參數(shù),Array在F#中是mutable類型的容器,我們可以修改里面的元素,訪問元素用Array.[i], 修改元素用Array.<-[i] = newValue(不要忘記中間的.)

      2.  for loop的基本形式為 for in do, 我們可以使用[start .. end]或[start .. step .. end]來構(gòu)建一個(gè)range,當(dāng)然,這里的range其實(shí)也是一個(gè)List

看完了內(nèi)部函數(shù),我們再接著往下看(原程序第12行)

 
 
 
  1. loop [] [2 .. n]

這里就很簡單了,調(diào)用我們剛剛定義的內(nèi)部函數(shù),(acc為空List [], 第二個(gè)參數(shù)為List [2 .. n]),其返回值(List acc)就是函數(shù)GetAllPrimesBefore的返回值,F(xiàn)#中函數(shù)有返回值時(shí)不需要敲return.

函數(shù)調(diào)用也很簡單,(不需要在參數(shù)與函數(shù)名之間加括號)

 
 
 
  1. let primesBefore100 = GetAllPrimesBefore 100

后記

1. F#中函數(shù)體內(nèi)可以定義新的值,變量和函數(shù)。(只在當(dāng)前函數(shù)體內(nèi)可見)。當(dāng)然,這樣做的好處顯而易見,我就不啰嗦了。

2. Recursive function是functional programming中很常用的一種算法實(shí)現(xiàn)方式。functional programming language往往會(huì)針對尾遞歸進(jìn)行特別的優(yōu)化,F(xiàn)#也不例外,所以我們需要盡可能的把遞歸寫成尾遞歸的形式,這個(gè)有時(shí)就需要像本文一樣借助accumulator來實(shí)現(xiàn)。

本文來自hiber的博客:《結(jié)合實(shí)例學(xué)習(xí)F#(一) --快速入門》。


當(dāng)前標(biāo)題:F#入門:基本語法,模式匹配及List
文章位置:http://m.5511xx.com/article/cdpdehd.html