如何将这段C#代码写成F#代码?涉及IT技术相关内容。

9

我习惯用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#中处理这种情况是否有更“优雅”的方式?

谢谢!

2个回答

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 *)

太好了!我知道一定有一种 F# 风格的方法可以做到这一点!我正在学习 F#,但我还没有习惯以函数式的方式思考。谢谢! - Gerardo Contijoch

8

将这个逻辑封装在函数中...

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

可能的情况是:

attempt getSomeObj |> orElse getSomeDefaultValue

虽然我选择了其他用户的答案作为有效答案,但我真的很喜欢attempt的写法。我从未想过要写出那样的东西。谢谢! - Gerardo Contijoch
不用谢。pad的答案阐述了解决方案的关键:在F#中,一切都是表达式,但我想指出其中涉及的模式。这些原语有时很方便,并且可以导致更易读的代码。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接