自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

F#入門(mén):基本語(yǔ)法,模式匹配及List

開(kāi)發(fā) 后端
F#是隨著VS2010 Beta版一起正式推出的另一個(gè)基于.NET平臺(tái)的語(yǔ)言,以函數(shù)式語(yǔ)言著稱(chēng)。這個(gè)F#入門(mén)文章介紹了F#的基本語(yǔ)法,模式匹配及List基本類(lèi)型。

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

F#入門(mén)代碼

  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 

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

  1. let GetAllPrimesBefore n = 

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

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

第二行,首先請(qǐng)注意該行與第一行相對(duì)有一個(gè)縮進(jìn)({TAB}),F#和Python一樣,也是通過(guò){TAB}縮進(jìn)來(lái)組織代碼結(jié)構(gòu)的。這一行我們定義了一個(gè)變量container,它的類(lèi)型是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  

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

  1. let rec loop acc = function 

F#入門(mén):模式匹配

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

  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í)在太廣了,所以就引入了一種簡(jiǎn)化版,這就是上面大家看到的等號(hào)后面的function的作用,我們可以把上面的例子簡(jiǎn)化成

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

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

F#入門(mén):List基本類(lèi)型

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

F#中List是immutable類(lèi)型,我們只能訪問(wèn)里面的值,不能改動(dòng)里面的值,任何改動(dòng)List的需求只能通過(guò)構(gòu)建新的List來(lái)實(shí)現(xiàn)。稍一思考,大家就會(huì)很快發(fā)現(xiàn)要實(shí)現(xiàn)一個(gè)高效的immutable list, 那最簡(jiǎn)單的就是對(duì)其頭結(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)的庫(kù)函數(shù)List.hd, List.tl,并且提供了:: (cons operator)來(lái)幫助我們方便的構(gòu)建一個(gè)List,比如1::2::[]就表示List [1;2] (注意1和2之間我用的是;不是, 如果寫(xiě)成[1,2],那個(gè)表示該List只有一個(gè)元素 (1,2),至于(1,2)是什么類(lèi)型,為了使文章盡量緊湊,我們今天就不講了)

有了上面這些知識(shí),再看本文一開(kāi)始的函數(shù)就簡(jiǎn)單多了

  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),略過(guò)當(dāng)前值,檢查接下來(lái)的值 loop acc tl

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

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

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

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

看完了內(nèi)部函數(shù),我們?cè)俳又驴矗ㄔ绦虻?2行)

  1. loop [] [2 .. n] 

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

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

  1. let primesBefore100 = GetAllPrimesBefore 100 

后記

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

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

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

【編輯推薦】

  1. C# Actor的尷尬與F#美麗外表下的遺憾
  2. 函數(shù)式編程語(yǔ)言F#:基于CLR的另一個(gè)頭等編程語(yǔ)言
  3. Visual Studio 2010爆F(xiàn)#二進(jìn)制兼容性問(wèn)題
  4. 推薦Visual Studio 2010中F#的一些資源
  5. Visual Studio 2010將正式包含F(xiàn)#
責(zé)任編輯:yangsai 來(lái)源: hiber的博客
相關(guān)推薦

2010-01-26 08:25:06

F#語(yǔ)法F#教程

2010-04-07 16:51:59

F#

2010-03-26 19:22:08

F#代理

2010-03-26 19:03:19

F#異步并行模式

2010-03-16 09:09:04

F#

2010-03-26 18:31:59

F#異步并行模式

2010-03-08 09:17:13

F#異步

2009-08-27 09:16:48

F#中DSL原型設(shè)計(jì)

2010-01-07 10:04:18

F#函數(shù)式編程

2010-01-15 08:33:13

F#F#類(lèi)型推斷F#教程

2009-08-13 17:39:48

F#數(shù)據(jù)類(lèi)型Discriminat

2011-06-09 09:52:41

F#

2009-08-19 09:42:34

F#并行排序算法

2009-09-10 14:18:59

Functional F#

2010-04-06 15:20:56

ASP.NET MVC

2009-12-04 09:16:44

Visual Stud

2009-11-16 09:05:46

CodeTimer

2012-11-06 10:01:35

ContinuatioF#

2009-12-14 09:04:10

F#運(yùn)算符

2009-12-11 13:59:35

F#
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)