F#和Scala都是混合语言,通常用于将传统面向对象代码与函数式代码桥接。
属于面向对象世界的概念是异常,而函数式世界在许多情况下更喜欢Option类型。为了包装依赖异常的现有库代码并使其更加函数化,我想要将抛出异常的代码“提取”为返回Option类型。
在Scala中,有一个很好的库函数可以“捕获所有”并转换为Option。它可以像这样使用:
import scala.util.control.Exception._
val functionalVersion = allCatch opt myFunction
请参见在Scala中,是否存在将异常转换为选项的预定义库函数?
现在我正在转向F#,但我仍然有同样的要求,但似乎找不到现有的实用程序函数来完成这个任务,并且我也很难自己实现一个。
我可以为单位函数(即操作)创建这样的包装器。
let catchAll f = try Some (f()) with | _ -> None
但问题在于我不想首先将所有异常抛出的代码都包装成一个操作。
例如,我希望包装数组索引运算符,使其不会抛出异常。
// Wrap out-of-bounds exception with option type
let maybeGetIndex (array: int[]) (index: int) = catchAll (fun () -> array.[index])
maybeGetIndex [| 1; 2; 3 |] 10 // -> None
然而,如果能够简单地编写如下代码,那就更好了。
(catchAll a.[index])
即在表达式被求值之前将catchAll应用于整个表达式。 (Scala可以通过按名称调用参数实现这一点,但似乎在F#中缺少此功能)
因此,这个问题有两个方面:
- 是否存在现有的库函数将异常包装成选项类型?
- 是否有一种语言特性可以让我实现它?
catchAll {[| 1; 2; 3 |].[1] }
会产生Some()
。 - Geroldreturn
,但这使它有点不太美观。 - Tomas Petricek