私はこれを行うための簡単な(方法と比較して、try catch
かなり簡単な)方法を見つけることができません:
try
Some (line.Split delimiter |> Array.map Int32.Parse)
with
|_ -> None
悪い(Parse
2回呼び出す)アプローチは次のようなものです。
let array = line.Split delimiter
let parseSucceed =
array |> Array.exist (Int32.TryParse >> fst >> not)
|> not
if parseSucceed then Some (array |> Array.map Int32.Parse) else None
そのようなタスクを実行する標準的な方法はありますか?これを処理するために再帰関数を作成する必要がありますか?
入力が配列ではなくストリーム/シーケンスである場合はどうなりますか?
アップデート:
@ダニエルの方法は素晴らしいです。
module Seq =
let tryCatch myFun (x: seq<_>) =
let rec loop acc (e: IEnumerator<_>) =
if e.MoveNext() then
match myFun e.Current with
| Some v -> loop (v::acc) e
| None -> (false, acc |> List.rev |> List.toSeq)
else
(true, acc |> List.rev |> List.toSeq)
use e = x.GetEnumerator()
loop [] e
let parse x =
printf "%d " x // log when the function is called.
if x > 3 then None else Some x
let tt myFun x =
let y = Seq.tryCatch myFun x
if fst y then
printfn "yes %A" (y |> snd |> Seq.toArray)
else
printfn "no %A" (y |> snd |> Seq.toArray)
tt parse [| 0;2;1;2;4;1;2 |]
tt parse [| 0;2;1;2 |]
>
0 2 1 2 4 no [|0; 2; 1; 2|] // parse is called minimum number of times
0 2 1 2 yes [|0; 2; 1; 2|]