c# f#

c# - Nombre Tuplas/Tipos anónimos en F#?



(4)

Aquí está mi opinión sobre la configuración de ruta del proyecto web predeterminado:

module RouteConfig = open System.Web.Mvc open System.Web.Routing let registerRoutes (routes: RouteCollection) = routes.IgnoreRoute("{resource}.axd/{*pathInfo}") /// create a pair, boxing the second item let inline (=>) a b = a, box b /// set the Defaults property from a given dictionary let setDefaults defaultDict (route : Route) = route.Defaults <- RouteValueDictionary(defaultDict) routes.MapRoute(name="Default", url="{controller}/{action}/{id}") |> setDefaults (dict ["controller" => "Home" "action" => "Index" "id" => UrlParameter.Optional])

en C # puedes hacer cosas como estas:

var a = new {name = "cow", sound = "moooo", omg = "wtfbbq"};

y en Python puedes hacer cosas como

a = t(name = "cow", sound = "moooo", omg = "wtfbbq")

No por defecto, por supuesto, pero es trivial implementar una clase t que te permita hacerlo. De hecho, hice exactamente eso cuando estaba trabajando con Python y me pareció increíblemente útil para contenedores pequeños desechables en los que desea poder acceder a los componentes por su nombre en lugar de por índice (lo cual es fácil de confundir).

Aparte de ese detalle, son básicamente idénticos a las tuplas en el nicho que sirven.

En particular, estoy viendo este código C # ahora:

routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults );

y es equivalente a F #

type Route = { controller : string action : string id : UrlParameter } routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters { controller = "Home"; action = "Index"; id = UrlParameter.Optional } // Parameter defaults )

Que es a la vez prolijo y repetitivo, por no mencionar bastante molesto. ¿Qué tan cerca puede llegar a este tipo de sintaxis en F #? No me importa saltar a través de algunos aros (¡incluso aros llameantes!) Ahora si eso significa que me dará algo útil para SECAR el código de esta manera.


El OP no describe el mejor uso del tipo anónimo. Se usan mejor cuando se usa LINQ para mapear a una clase arbitraria. Por ejemplo:

var results = context.Students .Where(x => x.CourseID = 12) .Select(x => new { StudentID = x.ID, Name = x.Forename + " " + x.Surname });

Sé que esto se puede hacer definiendo un nuevo tipo de registro, pero luego tiene dos lugares para mantener el código, (1) la definición del tipo de registro (2) donde lo ha usado.

En cambio, podría hacerse con una tupla, pero para acceder a campos individuales, debe usar la sintaxis de deconstrucción (studentId, name) todo el tiempo. Esto se vuelve difícil de manejar si tiene 5 elementos en la tupla. Prefiero escribir x y pulsar punto y decir inteligentemente qué campos están disponibles.


Me resulta más fácil de hacer

let route = routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}" // URL with parameters ) route.Defaults.Add("controller", "Home") route.Defaults.Add("action", "Index")

o

[ "controller", "Home" "action", "Index" ] |> List.iter route.Defaults.Add

En F #, evitaría llamar a sobrecargas que acepten tipos anónimos tanto como evitaría llamar a un método F # que acepte FSharpList desde C #. Esas son características específicas del idioma. Por lo general, hay una sobrecarga / solución alternativa independiente del idioma disponible.

EDITAR

Acabo de ver los documentos: he aquí otra forma de hacerlo

let inline (=>) a b = a, box b let defaults = dict [ "controller" => "Home" "action" => "Index" ] route.Defaults <- RouteValueDictionary(defaults)


No puede crear "registros anónimos" en F # - al usar tipos, puede usar tuplas que son anónimas, pero no llevan etiquetas o puede usar registros que deben declararse por adelantado y tienen etiquetas:

// Creating an anonymous tuple let route = ("Home", "Index", UrlParameter.Optional) // Declaration and creating of a record with named fields type Route = { controller : string; action : string; id : UrlParameter } let route = { controller = "Home"; action = "Index"; id = UrlParameter.Optional }

Técnicamente, el problema con los registros anónimos es que tendrían que definirse como clases reales en algún lugar (el tiempo de ejecución de .NET necesita un tipo), pero si el compilador los coloca en cada ensamblado, entonces dos registros anónimos con los mismos miembros podrían ser de tipos diferentes si se definieron en diferentes conjuntos.

Honestamente, creo que el ejemplo que publicaste es solo una mala decisión de diseño en ASP.NET: está haciendo un uso indebido de una función C # particular para hacer algo para lo que no fue diseñada. Puede que no sea tan malo como this , pero sigue siendo extraño. La biblioteca toma un tipo anónimo de C #, pero lo usa como un diccionario (es decir, lo usa simplemente como una buena forma de crear pares clave-valor, porque las propiedades que necesita especificar son dinámicas).

Por lo tanto, si usa ASP.NET desde F #, probablemente sea más fácil usar un enfoque alternativo donde no tenga que crear registros, si la API de ASP.NET proporciona alguna alternativa (como muestra Daniel, hay una mejor opción). forma de escribir eso).