f# language-features hidden-features

Características ocultas de F#



language-features hidden-features (11)

F # tiene una característica poco utilizada llamada "archivos de firma". Puede tener un gran archivo de implementación lleno de tipos / métodos / módulos / funciones públicos , pero luego puede ocultar y exponer selectivamente esa funcionalidad a la secuela del programa a través de un archivo de firma. Es decir, un archivo de firma actúa como un tipo de pantalla / filtro que le permite hacer entidades "públicas para este archivo" pero "privadas para el resto del programa".

Siento que esta es una característica bastante importante en la plataforma .Net, porque la única otra herramienta anterior que tiene para este tipo de encapsulación es ensamblados. Si tiene un componente pequeño con algunos tipos relacionados que desean poder ver los detalles internos de los demás, pero no quiere que esos tipos tengan todos esos bits públicos para todos , ¿qué puede hacer? Bueno, puedes hacer dos cosas:

  1. Puede colocar ese componente en un ensamblaje por separado y hacer que los miembros que esos tipos comparten sean "internos", y hacer que la parte estrecha que desea que todos los demás sean "públicos", o
  2. Simplemente marca las cosas internas "internas" pero dejas esos tipos en tu ensamblaje gigante y solo esperas que el resto del código en el ensamblaje elija no llamar a los miembros que solo fueron marcados como "internos" porque otro tipo necesitaba verlo .

En mi experiencia, en grandes proyectos de software, todos siempre hacen # 2, porque el # 1 no es inicial por varias razones (las personas no quieren 50 ensambles pequeños, quieren 1 o 2 o 3 ensamblajes grandes, para otros tal vez) buenas razones no relacionadas con el punto de encapsulación que estoy planteando (a un lado: todos mencionan ILMerge pero nadie lo usa)).

Entonces elegiste la opción # 2. Luego, un año después, finalmente decide refactorizar ese componente, y descubre que durante el año pasado, otros 17 lugares ahora recurren a ese método "interno" que en realidad solo estaba destinado a ese tipo de otro tipo, lo que lo hace realmente difícil factorizar ese bit porque ahora todos dependen de esos detalles de implementación. Gorrón.

El punto es que no hay una buena manera de crear un alcance / límite de encapsulación intra-ensamblado de tamaño moderado en .Net. Muchas veces "interno" es demasiado grande y "privado" es demasiado pequeño.

... hasta F #. Con los archivos de firma F #, puede crear un alcance de encapsulación de "este archivo de código fuente" marcando un montón de cosas como públicas dentro del archivo de implementación, para que todo el otro código en el archivo pueda verlo y festejarlo, pero luego use un archivo de firma para ocultar todos los detalles, espere la interfaz pública estrecha que ese componente expone al resto del mundo. Esto es feliz Defina tres tipos altamente relacionados en un archivo, permítales ver los detalles de implementación de los demás, pero solo exponga las cosas verdaderamente públicas a todos los demás. ¡Ganar!

Los archivos de firma quizás no sean la característica ideal para los límites de encapsulación dentro del ensamblaje, pero son la única característica que conozco, por lo que me aferro a ellos como una balsa salvavidas en el océano.

TL; DR

La complejidad es el enemigo. Los límites de encapsulación son un arma contra este enemigo. "privado" es una gran arma, pero a veces demasiado pequeña para ser aplicable, y "interna" a menudo es demasiado débil porque tanto código (todo el ensamblaje y todo InternalsVisibleTo) puede ver cosas internas. F # ofrece un alcance mayor que "privado a un tipo" pero más pequeño que "todo el conjunto", y eso es muy útil.

Este es el intento descarado de una pregunta C # similar.

Entonces, ¿cuáles son tus características favoritas ocultas (o no) de F #?

La mayoría de las funciones que he utilizado hasta ahora no están exactamente ocultas, pero han sido bastante refrescantes. Me gusta lo trivial que es sobrecargar a los operadores en comparación con decir C # o VB.NET.

Y Async<T> me ha ayudado a depilar un código realmente feo.

Todavía soy bastante nuevo en el lenguaje, así que sería genial saber qué otras características se usan en la naturaleza.



Los literales numéricos definidos por el usuario pueden definirse proporcionando un módulo cuyo nombre comience con NumericLiteral y que defina ciertos métodos ( FromZero , FromOne , etc.).

En particular, puede usar esto para proporcionar una sintaxis mucho más legible para llamar a LanguagePrimitives.GenericZero y LanguagePrimitives.GenericOne :

module NumericLiteralG = begin let inline FromZero() = LanguagePrimitives.GenericZero let inline FromOne() = LanguagePrimitives.GenericOne end let inline genericFactorial n = let rec fact n = if (n = 0G) then 1G else n * (fact (n - 1G)) fact n let flt = genericFactorial 30. let bigI = genericFactorial 30I


Los operadores en línea en tipos genéricos pueden tener diferentes restricciones genéricas:

type ''a Wrapper = Wrapper of ''a with static member inline (+)(Wrapper(a),Wrapper(b)) = Wrapper(a + b) static member inline Exp(Wrapper(a)) = Wrapper(exp a) let objWrapper = Wrapper(obj()) let intWrapper = (Wrapper 1) + (Wrapper 2) let fltWrapper = exp (Wrapper 1.0) (* won''''t compile *) let _ = exp (Wrapper 1)


No hay características ocultas, porque F # está en modo de diseño. Todo lo que tenemos es una Vista previa técnica, que cambia cada dos meses.

ver http://research.microsoft.com/fsharp/


Sí, F # no tiene características ''ocultas'', pero seguro tiene mucha potencia en el lenguaje simple. Una característica menos conocida del lenguaje, es donde básicamente puedes habilitar el tipado de pato a pesar de que F # está escrito de forma estática.


No realmente escondido , pero como una persona que no es de ML me escapó por un buen tiempo:

La coincidencia de patrones puede descomponerse arbitrariamente en las estructuras de datos.

Aquí hay un ejemplo de tupla anidada [increíblemente arbitraria]; esto funciona en listas o uniones o cualquier combinación de valores anidados:

let listEven = "Manipulating strings can be intriguing using F#".Split '' '' |> List.ofArray |> List.map (fun x -> (x.Length % 2 = 0, x.Contains "i"), x) |> List.choose ( function (true, true), s -> Some s | _, "F#" -> Some "language" | _ -> None )


Pasando --warnon:1182 al compilador activa las advertencias sobre variables no utilizadas; los nombres variables que comienzan con guión bajo son inmunes.


Me pregunto qué pasará si agregas

<appSettings> <add key="fsharp-navigationbar-enabled" value="true" /> </appSettings>

a su archivo devenv.exe.config? (Úselo bajo su propio riesgo.)


El uso de F # como lenguaje de scripting de utilidad puede ser menos apreciado. Los entusiastas de F # tienden a ser cuantiosos. A veces quieres algo para hacer una copia de seguridad de tus archivos MP3 (o docenas de servidores de bases de datos) que es un poco más robusto que el lote. He estado buscando un reemplazo moderno para jscript / vbscript. Últimamente, he usado IronPython, pero F # puede ser más completo y la interacción .NET es menos engorrosa.

Me gustan las funciones al curry para el valor de entretenimiento. Muestre una función curried a un programa puramente procedimental / OOP para al menos tres WTF. Empezar con esto es una mala forma de obtener F # convierte, sin embargo :)


Ver esta pregunta

F # operador "?"

para obtener información sobre el operador de la marca de interrogación y cómo proporciona el mecanismo de lenguaje básico para crear una función similar a "dinámica" en C #.