2014-12-09 89 views
3

我有一個關於在F#中使用do塊的約定的問題。主要是在使用.NET庫類和其他.NET代碼時出現這種情況。F#在do塊中打包語句

讓我給你舉個例子。

1.用做塊周圍包裹的語句:

let drawHelloName (width:int, height:int) name = 
    let bmp = new Bitmap(width, height) 
    use fnt = new Font("Arial", 12.0f) 
    use gr = Graphics.FromImage(bmp) 
    do 
     gr.Clear(Color.White) 
     gr.DrawString(name, fnt, Brushes.Black, PointF(10.0f, 10.0f)) 
    bmp 

2.如果沒有做塊:

let drawHelloName (width:int, height:int) name = 
    let bmp = new Bitmap(width, height) 
    use fnt = new Font("Arial", 12.0f) 
    use gr = Graphics.FromImage(bmp) 
    gr.Clear(Color.White) 
    gr.DrawString(name, fnt, Brushes.Black, PointF(10.0f, 10.0f)) 
    bmp 

現在在我的心目中,我覺得例1更清晰更多的是F#的觀點和風格。由於在函數式編程中處理語句並不是很「自然」,所以我們明確地將這些語句封裝在do塊中以表明它們是副作用。但我想知道,關於這個的公約是什麼?

+0

雖然一個獨立的方法調用出現在C#和F#一樣,F#斷言,這樣的調用返回'unit',這使得'do'在許多情況下是多餘的。 – Daniel 2014-12-09 14:55:21

回答

7

由於在函數式編程中處理語句並不真正「自然」,所以我們明確地將語句包裝在do塊中以顯示它們是副作用。

我同意你的意見。但是,如果你在野外研究F#代碼,他們在這件事上往往會鬆動。沒有嚴格的慣例,只要按照您認爲最適合您的方式行事即可。

另一點是塊是否爲我們希望明確控制其生命期的值創建新的範圍。例如,如果您想提前處置gr並繼續使用fnt,你的第一個功能可以被寫入:

let drawHelloName (width:int, height:int) name = 
    let bmp = new Bitmap(width, height) 
    use fnt = new Font("Arial", 12.0f) 
    do 
     use gr = Graphics.FromImage(bmp) 
     gr.Clear(Color.White) 
     gr.DrawString(name, fnt, Brushes.Black, PointF(10.0f, 10.0f)) 
    (* Continue to do something with 'fnt' *) 
    bmp 

,你必須使用do塊的另一個地方是隱式的構造函數裏面例如

type T(width, height) = 
    let bmp = new Bitmap(width, height) 
    use fnt = new Font("Arial", 12.0f) 
    use gr = Graphics.FromImage(bmp) 
    do 
     gr.Clear(Color.White) 
     gr.DrawString(name, fnt, Brushes.Black, PointF(10.0f, 10.0f)) 
+1

唉,F#規範中沒有定義「do block」。我們在模塊和主要構造函數中都有'do語句',後者甚至是'static do'。數值或函數定義中的「do」行爲似乎等同於「加了括號的表達式」或「塊表達式」(參見§6.5.1括號和表達式_),但沒有人會將它們與副作用聯繫起來。 – kaefer 2014-12-09 15:18:58

+0

@kaefer究竟是什麼區別? – 2014-12-09 17:37:01

+0

區別在於'unit'類型的聲明。另外,'type X()= do 1'會得到一個編譯錯誤,而'Y = do 1'或'let z = do 1'只是警告 – kaefer 2014-12-09 21:17:02