2014-07-16 66 views
10

我注意到下面的代碼編譯和VS 2013的工作原理:爲什麼在功能內允許「做」?

let f() = 
    do Console.WriteLine(41) 
    42 

但看F#3.0規範時,我找不到任何do提及使用這種方式。據我所知,do可以有以下用途:

  • 作爲環的一部分(例如while expr do expr done),這是不是這裏的情況。
  • 內部計算表達式,例如:

    seq { 
        for i in 1..2 do 
        do Console.WriteLine(i) 
        yield i * 2 
    } 
    

    ,這裏不是這種情況要麼,f不含任何計算表達式。

    雖然這裏讓我困惑的是,根據規範,do應該跟着in。由於輕量級語法,in應該是可選的,但在此處添加它會導致編譯錯誤(「未預期的令牌」或「不完整的表達式」)。

  • 聲明在模塊或類中。這裏也不是這種情況,do位於函數內部,不在模塊或類中。

我也注意到,與#light "off",代碼不編譯(「意外的關鍵字結合‘做’」),但我沒有發現任何會在輕量級語法部分要麼解釋。

基於這一切,我假設在函數內部使用do這種方式不應該編譯,但它確實如此。我錯過了規範中的一些東西嗎?或者這實際上是編譯器或規範中的錯誤?

+2

它被稱爲'do'綁定。我在規範中找不到它,但它[在MSDN上記錄](http://msdn.microsoft.com/en-us/library/dd393786.aspx)。 – Daniel

+0

@Daniel這是我提到的第三種情況,在模塊內部做「 「當你想要獨立於函數執行代碼*時使用do綁定*」 – svick

+1

完成引用:_獨立於函數*或值定義* ._第二種情況可能適用於函數。 – Daniel

回答

7

documentation on MSDN

do結合使用而不定義函數或值來執行代碼。

即使該規範沒有包含允許的地方的完整列表,但它僅僅是一個表達式,聲明爲unit類型。一些示例:

if ((do()); true) then() 
let x: unit = do() 

它通常被省略。前面的每個例子都是有效的,沒有do。因此,do僅服務於斷言表達式爲unit

+0

我認爲該規範不允許使用它,因爲它沒有被列爲'expr'(§6和§A.2.3)的選項之一。 – svick

+0

在過去的幾年裏,我見過很多用於函數或方法的'do'的例子。如果這種行爲不是有意的,那麼這一點事實上是有效的。但是,我認爲情況並非如此,在這一點上規範並不完整。 – Daniel

0

通過F# 3.0 specification表達式語法場地具有do expr作爲class-function-or-value-defn(類型)選擇[8章,A.2.5]和module-function-or-value-defn(模塊)[CH 10,A.2.1.1]。

我實際上並不在spec這裏function-defn可以有不止一個表達式看到,只要所有,但最後一個評估,以unit - 或者說所有,但在確定職能的最後一個表達式被忽略返回值。

所以,這似乎是文件中的疏忽。

+0

「我實際上沒有在規範中看到'function-defn'可以有多個表達式」這是多虧'expr = expr; expr'規則以及輕量級語法使分號可選的事實。 – svick