2013-04-08 1 views
9

я привык писать код, как это в C#:Как написать этот C# код в F #

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

obj.DoSomething(); 

Это, как я перевел его в F # (объект является список):

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 #, и я до сих пор не привык мыслить функционально. Спасибо! –

8

Обертывания этой логики в функциях ...

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

... это может быть:

attempt getSomeObj |> orElse getSomeDefaultValue 
+0

Хотя я выбрал какой-то другой ответ пользователя как действительный, мне очень нравится, как была написана «попытка». Я никогда не думал писать что-то подобное. Спасибо! –

+0

Добро пожаловать. Ответ на пэд иллюстрирует суть решения: все это выражение в F #, но я хотел указать на шаблоны. Примитивы, подобные этим, могут быть удобными и иногда приводят к появлению более читаемого кода. – Daniel