結合例項學習F 一 快速入門

2022-05-08 10:06:07 字數 4437 閱讀 6415

f#隨著vsts 2010 beta1 發布也有一段時間了,園子裡應該也有不少人對它感興趣吧。下面的例子是我在學f# 基本語法時寫的乙個簡單sieve of eratosthenes 實現,通過剖析這一小段**,我希望大家能對f#有個簡單認識,並能自己寫一些簡單的小程式。

1let

getallprimesbefore n = 

2let

container = array.create (n+1) 

03letrec

loop acc = 

function4|

->

list.rev acc5|

hd::tl 

->6if

container.[hd] =

1then

7loop acc tl

8else

9for

j in

[hd .. hd .. n] 

do10

container.[j] 

<-111

loop (hd::acc) tl    

12loop  [

2.. n]

1314

letprimesbefore120 = getallprimesbefore 

120廢話少說,直接進入正題吧

1let

getallprimesbefore n =

第一行,申明函式getallprimesbefore, 並且該函式有乙個引數n, 在這裡我沒有指定n的型別,因為編繹器可以通過函式體對n的型別進去推斷,比如在本例中,n就是int型別,當然我們也可以顯示的指定n的型別,比如 let getallprimesbefore (n:int),這樣我們就指定了n為int型 (注意:(n:int)中的括號不能省略,let getallprimesbefore n : int 的意思是該函式返回的值的int型)。說完了引數,再說下返回值,同樣,編繹器會根據函式體上下文對返回值型別進去推斷,所以我們不需要申明返回型別。

2let

container = array.create (n+1) 

0第二行,首先請注意該行與第一行相對有乙個縮排(),f#和python一樣,也是通過縮進來組織**結構的。這一行我們定義了乙個變數container,它的型別是array,大小為 n+1, 並且值全部初使化為0

1let

recloop acc = 

function2|

->

list.rev acc3|

hd::tl 

->4if

container.[hd] =

1then

5loop acc tl

6else

7for

j in

[hd .. hd .. n] do8

container.[j] 

<-19

loop (hd::acc) tl 

接下來就是這個函式的主要部分了(原程式中的3-11行),首先我們定義了乙個遞迴函式(我們發現定義遞迴函式需要加rec關鍵字)。它接受兩個引數,acc和乙個list,有朋友可能要問了,這裡明明我只看到乙個引數acc,你說的那個list在哪呢?可能有細心的朋友也發現了這裡的函式定義不光前面有rec,在等號後面還加了個function,那麼function是做什麼用的呢?

letrec

loop acc = 

function

這裡我需要首先講一下pattern matching, pattern matching有些類似於c#中的switch語句(當然它要比c#中的switch強大許多,但這不是本文的目地,所以略去不表),可以根據expr的值去執行某一具體分支,它的基本語法也很簡單,我們還是結合乙個具體例項來看一下(例子比較簡單,只是為了說明問題)。 這個例子大家很容易看懂吧,我就不詳細解釋了,只是說明一點,'_'用來匹配所有別的情況。

letshowgreeting laguageinuse = 

match

laguageinuse 

with|"

c#"->

printfn 

"hello, c# developer!"|

"f#"->

printfn 

"hello, f# developer!"|

_ ->

printfn 

"hello, other developers!

"因為pattern matching在f#中的使用範圍實在太廣了,所以就引入了一種簡化版,這就是上面大家看到的等號後面的function的作用,我們可以把上面的例子簡化成

letshowgreeting  = 

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)是什麼型別,為了使文章盡量緊湊,我們今天就不講了)

有了上面這些知識,再看本文一開始的函式就簡單多了

letrec

loop acc = 

function| 

->

list.rev acc

|hd::tl 

->

ifcontainer.[hd] =

1then

loop acc tl

else

forj 

in[hd .. hd .. n] 

docontainer.[j] 

<-

1loop (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.<-[i] = newvalue(不要忘記中間的.)

2.  for loop的基本形式為 for in do, 我們可以使用[start .. end]或[start .. step .. end]來構建乙個range,當然,這裡的range其實也是乙個list

看完了內部函式,我們再接著往下看(原程式第12行)

loop  [

2.. n]

這裡就很簡單了,呼叫我們剛剛定義的內部函式,(acc為空list , 第二個引數為list [2 .. n]),其返回值(list acc)就是函式getallprimesbefore的返回值,f#中函式有返回值時不需要敲return.

函式呼叫也很簡單,(不需要在引數與函式名之間加括號)

letprimesbefore100 = getallprimesbefore 

100後記

1. f#中函式體內可以定義新的值,變數和函式。(只在當前函式體內可見)。當然,這樣做的好處顯而易見,我就不囉嗦了。

2. recursive function是functional programming中很常用的一種演算法實現方式。functional programming language往往會針對尾遞迴進行特別的優化,f#也不例外,所以我們需要盡可能的把遞迴寫成尾遞迴的形式,這個有時就需要像本文一樣借助accumulator來實現。

《結合例項學習f#》

1. 快速入門

2. 基本資料型別discriminated unions

F 入門學習(一)

開啟專案 6 3 6.0 3.0 6 3.0 會有波浪線,預能感知,藍色警告可以執行 字元型let x1 財 val x1 char 財 注釋let x1 財 一行注釋 哈哈 我是多行 注釋 串型別 f 是強型別語言 必須把型別分的清清楚楚的意思。val it string f 是強型別語言 用來幹...

Python學習(一) 快速入門

因為boss要求開始學習python,參考教材是 python核心程式設計 第二版 用的環境是ubuntu 15.04。程式輸出 使用print語句,這個和c的printf 類似。print語句缺省會給每一行新增乙個換行符,而只要在print語句最後新增乙個逗號,就可以使得輸出的元素排列在同一行。p...

CSS快速入門學習一

一 css語法 h1 color blue font size 12px h1就是html的標籤,又叫選被器,是被選擇樣式化的物件,color blue 就是效果一,font size 12px 效果二 二 來個例子 p 或者這樣,更方便讀取 p放到html裡的 就是 hello world thi...