f# - sirve - Opcionalmente tomando el primer elemento en una secuencia.
tags de texto html (2)
Creo que (b) es probablemente el más idiomático, por la misma razón que dio @Ramon.
Creo que la falta de Seq.tryHead
significa que no es muy común.
No estoy seguro, pero supongo que los lenguajes funcionales con inferencia de tipo Hindley-Milner en general son escasos sobre la implementación de tales funciones específicas en los tipos de colección porque la sobrecarga no está disponible y la composición de las funciones de orden superior se puede hacer de forma tersa.
Por ejemplo, las extensiones C # Linq son mucho más exhaustivas que las funciones en el módulo Seq
F # (que a su vez es más exhaustiva que las funciones en tipos de colección concretos), e incluso tiene IEnumerable.FirstOrDefault
. Prácticamente cada sobrecarga tiene una variación que realiza un map
.
Creo que el énfasis en la coincidencia de patrones y los tipos concretos como la list
también es una razón.
Ahora, la mayoría de lo anterior es especulación, pero creo que puedo tener una idea más cercana a ser objetivo. Creo que muchas veces tryPick
y tryFind
se pueden usar en primer lugar en lugar de filter |> tryHead
. Por ejemplo, me encuentro escribiendo código como el siguiente con bastante frecuencia:
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)
en lugar de como
...
seq {
for name in ["a";"b";"c"] do
match ty.GetMethod(name) with
| null -> ()
| mi -> yield mi
} |> tryHead
Necesito una función como Seq.head
, pero devolver None
lugar de lanzar una excepción cuando la secuencia está vacía, es decir, seq<''T> -> ''T option
.
Hay miles de maneras de hacer esto. Aquí hay varios:
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
es el que yo uso. Dos preguntas:
- ¿Hay alguna forma particularmente idiomática de hacer esto?
- Ya que no hay
Seq.tryHead
funciónSeq.tryHead
incorporada, ¿eso indica que esto no debería ser necesario, es poco común o se implementa mejor sin una función?
ACTUALIZAR
tryHead
se ha agregado a la biblioteca estándar en F # 4.0 . Podrías definir:
let seqTryHead s = Seq.tryPick Some s
Es de tipo seq<''a> -> ''a option
. Tenga en cuenta que no reduzco la versión beta debido a la limitación del valor genérico.