F#在do块中包装语句

时间:2014-12-09 12:34:11

标签: f# functional-programming conventions statements

我有一个关于在F#中使用do块的约定的问题。在使用.NET库类和其他.NET代码时,首先会出现这种情况。

让我举个例子。

1。使用do块包含语句:

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块中以表明它们是副作用。但我想知道,关于这个的惯例是什么?

1 个答案:

答案 0 :(得分:7)

  

由于在函数式编程中处理语句并不是“自然”,我们将语句显式地包装在do块中以表明它们是副作用。

我同意你的看法。但是,如果你在野外研究F#代码,那么它们往往会松散。没有严格的约定,只要遵循您认为最适合您的方式。

另一点是,do块为我们想要明确控制其生命周期的值创建新的范围。例如,如果您希望先处理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))