2013-04-08 36 views
9

我以前寫這樣的代碼在C#:如何寫在F#此C#代碼

SomeObj obj; 
try{ 
    // this may throw SomeException 
    obj = GetSomeObj(); 
}catch(SomeException){ 
    // Log error... 
    obj = GetSomeDefaultValue(); 
} 

obj.DoSomething(); 

這是我翻譯了它在F#的方式(OBJ是一個列表):

let mutable obj = [] 
try 
    obj <- getSomeObj 
with 
    | ex -> 
     // Log ex 
     obj <- getSomeDefaultValue 

doSomething obj 

有沒有辦法在F#中做到這一點,而不使用可變變量?在F#中處理這種情況是否有更「優雅」的方式?

謝謝!

回答

20

的F#-ish辦法就是返還相同種類表達的兩個分支:

let obj = 
    try 
     getSomeObj() 
    with 
    | ex -> 
     // Log ex 
     getSomeDefaultValue() 

doSomething obj 

在F#中,你可以使用option型處理異常。如果沒有明顯的默認值,這是一個優點,編譯器會強制您處理異常情況。

let objOpt = 
    try 
     Some(getSomeObj()) 
    with 
    | ex -> 
     // Log ex 
     None 

match objOpt with 
| Some obj -> doSomething obj 
| None -> (* Do something else *) 
+0

太好了!我知道必須有一種方法可以用F#方式來實現這一點! 我正在學習F#,我還沒有習慣以功能的方式思考。謝謝! – 2013-04-08 15:08:31

8

包裝這樣的邏輯函數...

let attempt f = try Some(f()) with _ -> None 
let orElse f = function None -> f() | Some x -> x 

......它可能是:

attempt getSomeObj |> orElse getSomeDefaultValue 
+0

儘管我已經選擇了一些其他的用戶答案,但我確實很喜歡'attempt'的寫法。我從來沒有想過要寫這樣的東西。 謝謝! – 2013-04-08 15:16:28

+0

不客氣。 pad的答案說明了解決方案的癥結所在:一切都是F#中的表達式,但我想指出所涉及的模式。像這樣的原語可能很方便,並且有時會導致更易讀的代碼。 – Daniel 2013-04-08 15:27:37