2008-10-08 18 views
23

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

¿Cuáles son sus características F # ocultas (o no) favoritas?

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

Y Async<T> me ha ayudado a depilar algunos códigos realmente feos.

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

Respuesta

1

No hay funciones 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/

+2

Supongo que todas las características están ocultas de alguna manera;) – wishi

6

Sí, F # no tiene ningún características 'ocultas', pero seguro que tiene mucho poder embalado en un lenguaje sencillo. Una característica menos conocida del lenguaje es donde básicamente puede enable duck typing a pesar de que F # está escrito de forma estática.

3

El uso de F # como lenguaje de scripting de utilidad puede ser muy 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 gusta curried functions para el valor de entretenimiento. Muestre una función curried a un programa puramente procedimental/OOP para al menos tres WTF. A partir de esto es una mala manera de conseguir F # conversos, aunque :)

+0

Me gusta usar FSI para pequeños guiones, y en realidad he usado algunos archivos .fsx para cosas. Sin embargo, al menos en mi experiencia, el tiempo de inicio requerido para los archivos .fsx es demasiado para scripting de propósito general. Todavía prefiero los archivos por lotes y los scripts de Perl para las secuencias de comandos. – Juliet

+0

Prueba PowerShell y no te arrepentirás :) – stej

6

Ver esta pregunta

F# operator "?"

para obtener información sobre el operador de signo de interrogación y cómo se proporciona el mecanismo lenguaje básico para construir una función similar a 'dinámica' en C#.

10

F # tiene una característica poco utilizada llamada "archivos de firma". Puede tener un gran archivo de implementación lleno de public types/methods/modules/functions, 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 sorprendente en la plataforma .Net, porque la única otra herramienta anterior que tiene para este tipo de encapsulamiento son los ensamblajes. Si tiene un componente pequeño con algunos tipos relacionados que desean poder ver los detalles internos de cada uno, pero no desea que esos tipos tengan todos esos bits públicos en todos,, ¿qué puede hacer?Bueno, puede hacer dos cosas:

  1. Se puede retener ese componente en un ensamblaje separado, y hacer que los miembros de que esos tipos de acción, deberían "interno", y hacer que la parte estrecha desea que los demás para ver sea " public ", o
  2. Simplemente marque las cosas internas" internas "pero deje esos tipos en su ensamblaje gigante y solo espero que todos los demás códigos en el ensamblaje elijan no llamar a los miembros que solo fueron marcados como 'internos' porque otro tipo necesitaba verlo.

En mi experiencia, en proyectos de software grandes, todos siempre hacen # 2, porque # 1 no es arrancador por varias razones (las personas no quieren 50 ensamblajes pequeños, quieren 1 o 2 o 3 grandes asambleas, por otras razones quizás buenas sin relación con el punto de encapsulación que estoy planteando (aparte: todos mencionan ILMerge pero nadie lo usa)).

Así que eligió la opción 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 realmente públicas a todos los demás. ¡Ganar!

Los archivos de firmas no son quizás la característica ideales para los límites de encapsulación intra-montaje, pero son la única de estas características que sé, y por lo que se aferran 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.

2

operadores inlined 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) 
+0

Solo para aclarar, ¿qué pasaría si (+) y Exp no se declararan como en línea? – Joh

+0

@Joh: Los operadores ya no serían polimórficos, por lo que, por ejemplo, solo podría usar el operador (+) en un único tipo de Contenedor dentro de su programa. Todo el código que he escrito arriba todavía funcionaría, pero con los operadores en línea, también podríamos agregar dos 'Wrappers flotantes 'también. – kvb

29

definidos por el usuario literales numéricos pueden ser definidos por proporcionar un módulo cuyo nombre comienza con NumericLiteral y que define ciertos métodos (FromZero, FromOne, etc.)

En particular, se puede usar esta información para proporcionar una sintaxis mucho más legible para llamar 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 
+2

Idea impresionante: debe estar habilitada de manera predeterminada. – forki23

+0

Este es un truco muy bueno, pero parece funcionar solo con G, N, Q, R y Z. – Gustavo

8

Pasando --warnon:1182 al compilador convierte en advertencias acerca de las variables utilizadas; los nombres variables que comienzan con guión bajo son inmunes.

+0

¡Gracias! ¡Esto no estaba en la página de Opciones del compilador! Verdaderamente escondido. –

+1

Interesante, a partir de F # 2.0, el compilador emite esta advertencia: FSC: advertencia FS0075: La opción de línea de comando '--warnon' es para uso interno solamente –

5

En realidad, no ocultos, sino como una persona no-ML esto me escaparon durante bastante tiempo:

patrón de coincidencia puede descomponer profundidad arbitraria 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 los 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) 
9

Me pregunto lo que sucede si se agrega

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

a su archivo Devenv.exe.config? (Usar bajo su propio riesgo.)

+5

¿Alguna posibilidad de que nos lo haga saber sin que nosotros realmente lo intentemos? –

+0

¿Hay alguna razón por la que no deba dejar esto? Es bueno tener ¿Sabes si estará en vNext? – Daniel

+0

No está bien probado, posiblemente haga que VS sea más propenso a fallar. Aún no sé si estará en vNext ... también hay tal vez "Solution Navigator", y tengo que ver qué podemos incluir en el calendario ... – Brian