I need a function like Seq.head
, but returning None
instead of throwing an exception when the sequence is empty, i.e., seq<'T> -> 'T option
.
There are a jillion ways to do this. Here are several:
let items = Seq.init 10 id
let a = Seq.tryFind (fun _ -> true) items
let b = Seq.tryPick Some items
let c = if Seq.isEmpty items then None else Some (Seq.head items)
let d =
use e = items.GetEnumerator()
if e.MoveNext() then Some e.Current
else None
b
is the one I use. Two questions:
Seq.tryHead
function, does that indicate this shouldn't be necessary, is uncommon, or is better implemented without a function?tryHead
has been added to the standard library in F# 4.0.
I think (b) is probably the most idiomatic, for the same reason @Ramon gave.
I think the lack of Seq.tryHead
just means that it is not super common.
I'm not sure, but my guess is that functional languages with Hindley-Milner type inference in general are sparse about implementing such specific functions on collection types because overloading isn't available and composing higher-order functions can be done tersely.
For example, C# Linq extensions are much more exhaustive than functions in F#'s Seq
module (which itself is more exhaustive than functions on concrete collection types), and even has IEnumerable.FirstOrDefault
. Practically every overload has a variation which performs a map
.
I think emphasis on pattern matching and concrete types like list
is also a reason.
Now, most of the above is speculation, but I think I may have a notion closer to being objective. I think a lot of the time tryPick
and tryFind
can be used in the first place instead of filter |> tryHead
. For example, I find myself writing code like the following fairly frequently:
open System.Reflection
let ty = typeof<System.String> //suppose this type is actually unknown at compile time
seq {
for name in ["a";"b";"c"] do
yield ty.GetMethod(name)
} |> Seq.tryFind((<>)null)
instead of like
...
seq {
for name in ["a";"b";"c"] do
match ty.GetMethod(name) with
| null -> ()
| mi -> yield mi
} |> tryHead
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With