Sintaxis del inicializador de la colección F#
inline (6)
Como dice Jared, no hay soporte incorporado para esto para colecciones arbitrarias. Sin embargo, el código C # es solo azúcar sintáctica para las llamadas al método Add
, por lo que podría traducirlo a:
let coll = MyCollectionType()
["One", 1; "Two", 2] |> Seq.iter coll.Add
Si desea obtener fantasía, puede crear una definición en inline
para simplificar esto aún más:
let inline initCollection s =
let coll = new ^t()
Seq.iter (fun (k,v) -> (^t : (member Add : ''a * ''b -> unit) coll, k, v)) s
coll
let d:System.Collections.Generic.Dictionary<_,_> = initCollection ["One",1; "Two",2]
¿Cuál es la sintaxis del inicializador de colección en F #? En C # puedes escribir algo como:
new Dictionary<string, int>() {
{"One", 1},
{"two", 2}}
¿Cómo hago lo mismo en F #? Supongo que podría rodar mi propia sintaxis, pero parece que ya debería haber una incorporada o estándar.
Dado que la sintaxis del inicializador de la colección C # es azúcar sintáctica para llamar a .Add
y eso implica una colección mutable, no estoy seguro de que vea tal sintaxis en F #. Es inicializar todo de una vez según la respuesta de JaredPar, o hacerlo manualmente.
La falta de un inicializador de colección es molesta para algunas API centradas en XAML como Workflow 4.0, que se basan en inicializadores de colección en lugar de ctors, por ejemplo
new Sequence { Activities = { WriteLine { Text = "In the sequence!" } } };
En tales casos, el imperativo .Add () es incómodo porque el valor es conceptualmente declarativo a pesar de que es técnicamente mutable / imperativo. Sin embargo, no hay una clase base común para el conjunto de todas las actividades que declaran un elemento secundario de Actividades: el miembro "Actividades" es un patrón y no una interfaz, por lo que no puede escribir una función de ayuda normal que agregue elementos secundarios a cualquier actividad. Afortunadamente, las restricciones de miembros F # vienen al rescate.
Para escribir esto:
Sequence() |> add [Sequence(DisplayName="InnerSeq"); WriteLine(Text = InArgument<_>("In the sequence!"))]
Primero debe definir una función auxiliar en línea llamada "agregar":
let inline add (children: Activity seq) =
let inline doAdd (activity: ^Activity) : ^Activity when ^Activity : (member get_Activities : unit -> Activity Collection) =
let collection = (^Activity : (member get_Activities : unit -> Activity Collection) (activity))
for child in children do
collection.Add(child)
activity
doAdd
Esto todavía no es tan bueno como la sintaxis de C #, pero al menos sigue siendo declarativo. En mi humilde opinión, esto no es tanto una falla de F # como las API centradas en el inicializador de recopilación, pero al menos F # permite una solución alternativa.
No creo que F # tenga una sintaxis explícita de inicializador de colección. Sin embargo, normalmente es muy fácil inicializar las colecciones de F #. Por ejemplo
let map = [ ("One", 1); ("Two", 2) ] |> Map.ofSeq
Llegar a las colecciones BCL suele ser un poco más difícil porque no siempre tienen las funciones de conversión prácticas. Dictionary<TKey, TValue>
funciona porque puedes usar el método LINQ
let map =
let list = [ ("One", 1); ("Two", 2) ]
System.Linq.Enumerable.ToDictionary(list, fst, snd)
Para elaborar un poco sobre la inicialización de la colección en F #, aquí hay algunos ejemplos:
diccionario de solo lectura
dict [ (1, "a"); (2, "b"); (3, "c") ]
seq (IEnumerable <T>)
seq { 0 .. 99 }
lista
[1; 2; 3; 4; 5]
conjunto
set [1; 2; 3; 4; 5]
formación
[| 1; 2; 3; 4; 5 |]
Puedes usar el mismo:
open System.Collections.Generic
Dictionary<int, string>(dict [ (1, "a"); (2, "b"); (3, "c") ])
Aclamaciones.