以下代码对printfn
s。
我该如何解决?即使其中一个项目失败,我也希望Seq.map
循环继续。
// files should be a Seq of record
let files = seqOfStrs |> Seq.map(fun s ->
match s with
| Helper.ParseRegex "(\w+) xxxxx" month ->
let currentMonth = .....
if currentMonth = month.[0] then
doc.Load(shelf)
// parse doc and return record type. Omitted
else
printfn "Expect %s found %s." currentMonth month.[0] //Error
| _ ->
printfn "No '(Month) Payment Data On Line' prompt." //Error
答案 0 :(得分:7)
问题在于你逻辑的不同分支正在产生不同的东西。在"省略"您显然返回xxxx类型的值(例如string
),但在printfn
次调用的其他分支中,您返回时没有值,这在F#中是表示为unit
,在其他语言中通常称为void
。
如果您不希望循环继续,最简单的答案就是在这些情况下抛出异常,例如:
failwithf "Expect %s found %s." currentMonth month.[0]
failwithf
的静态返回类型可以是任何类型,包括string
,因为它实际上从未返回,因此实际上不必生成该类型的值。
鉴于您确实希望代码继续,您可以返回一个空字符串或某种失败值,例如:
printfn "Expect %s found %s." currentMonth month.[0] //Error
"failed"
现在所有分支都具有相同的类型,因此您的代码将编译,但您必须小心,调用者不会意外地将此值解释为某些有效结果,这就是为什么抛出异常通常更清晰。
更简洁的方法是使用option
值来表示成功或失败,即在正确的情况下返回Some "..."
,在错误情况下返回None
。当失败是调用代码想要处理的常见事件而不是仅向用户报告问题并中止时,这种方法更好:
// files should be a Seq of record
let files = seqOfStrs |> Seq.map(fun s ->
match s with
| Helper.ParseRegex "(\w+) xxxxx" month ->
let currentMonth = .....
if currentMonth = month.[0] then
doc.Load(shelf)
// parse doc and produce record type.
Some record
else
printfn "Expect %s found %s." currentMonth month.[0] //Error
None
| _ ->
printfn "No '(Month) Payment Data On Line' prompt." //Error
None
您现在需要确定您希望files
包含的内容 - 您是否希望显式None
值显示某些内容失败,或者您只是希望序列包含正确的内容价值并完全忽略失败?
如果您想要显式值,那么您可以保留option
值,并且您将获得seq<string option>
结果。请注意,此类型只是seq<option<string>>
的语法糖,反映了F#的O&#39; Caml遗产。
如果您只想省略它们,请将Seq.map
来电替换为Seq.choose
,这将删除所有None
值并删除Some
包装,离开您当前代码正在尝试生成seq<string>
。