2016-06-11 51 views
4

F#中的'do'關鍵字的一個更微妙的用途是能夠註釋返回單元(aka語句)的表達式。例如,我經常在函數定義中這樣做,以清楚說明返回類型是單位,並且還指示編譯器爲我檢查此類型。例如:適當的F#中的綁定風格#

let restart agent = do agent.Post Restart 

但是我不確定'do'關鍵字占主導地位的是F#社區。

什麼是使用「做」關鍵字在這個例子中,正確的方法:

// Annotate each statement 
let move source destination = 
    do copy source destination 
    do clear source 

// Annotate the statements as one block 
let move source destination = 
    do 
     copy source destination 
     clear source 

// Just annotate the "return" statement 
let move source destination = 
    copy source destination 
    do clear source 

// Perhaps don't annotate at all? 
let move source destination = 
    copy source destination 
    clear source 

回答

3

我很少看到F#代碼用於此目的(將unit表達式)do。您所描述的大多數類型檢測已經在沒有它的情況下自動執行,以FS0020關於未使用值的警告形式進行。

如果你簡單地寫

let move source destination = 
    copy source destination 
    clear source 

然後三種情況之一會發生:

  • 兩個copyclear返回unit

    在這種情況下,一切都很好。

  • copy返回除單元

    其他

    在這種情況下一個類型將收到FS0020警告關於忽略值:

    表達copy source destination返回當前正被忽略的int。如果你不需要這個值,你應該使用忽略函數明確地忽略它,例如ignore (copy source destination)或將結果與名稱綁定let result = copy source destination

  • copy回報單元,clear返回比unit

    在這種情況下其他類型不會有警告,但move將具有相同類型clear,而這種差異將在調用表現網站爲move,你會得到與上面相同的警告。

所以do的類型檢查的目的,效用相當有限:僅在過去的情況下,它會有所作爲,通過使警告在原線路出現迫使你從move導航到它,而不是' (或可能 - 如果move是其範圍中的最後一行 - 從move的呼叫者的呼叫站點等等)。如果clear返回一個值(例如指示清除是否成功的布爾值),那麼您肯定會想要將該信息傳播到調用鏈上!

這就是說,這是一個非常簡單的標誌,(IMO)不會在一定程度上損害可讀性,並且可以改進它。考慮到F#社區對喜歡禁用燈語法(#light "off")並手動輸入分號和end標記的少數用戶沒有問題,我無法想象do會在任何地方擡起任何眉毛。

+0

很好的答案!我知道FS0020,但我更喜歡在這種情況下明確表達,尤其是因爲單位表達意味着副作用,這迫使您考慮每一個這樣的用法,並且引起讀者的注意。說到分號,另一種選擇可能是:複製源目標;明確的來源 – monoceres