シーケンスで列挙しつつ最後の要素かどうか判定する

リストの場合は再帰関数とパターンマッチングでできるんですが、シーケンスだとそうもいかず冗長になっちゃうなぁと思った。

リスト

[<Test>]
let ``detect last element of list`` () =
let rec loop = function
| [] -> ()
| [x] -> printfn "last %d" x
| h :: t -> printfn "%d" h ; loop t
let list = [ 1 .. 5 ]
loop list

シーケンス

[<Test>]
let ``detect last element of seq`` () =
let seq = seq { 1 .. 5 }
use e = seq.GetEnumerator()
(e, e.MoveNext())
|> Seq.unfold
(fun (e, hasCurrent) ->
if
hasCurrent then
let
current = e.Current
let hasNext = e.MoveNext()
Some ( (current, hasNext), (e, hasNext))
else
None)
|> Seq.iter
(fun (e, hasNext) ->
if
hasNext then
printfn "%d" e
else
printfn "last %d" e)

出力結果

上のどちらのコードを動かしてもこういった結果になる。

1
2
3
4
last 5