Caratteristiche nascoste di F #

Questo è il tentativo spudorato di una domanda simile a C # .

Quindi quali sono le tue caratteristiche preferite di F # (o no) preferite?

La maggior parte delle funzioni che ho usato fino ad ora non sono esattamente nascoste ma sono state piuttosto rinfrescanti. Come quanto sia banale sovraccaricare gli operatori rispetto a C # o VB.NET.

E Async mi ha aiutato a cancellare un codice davvero brutto.

Sono abbastanza nuovo per la lingua, quindi sarebbe bello sapere quali altre funzionalità vengono utilizzate in natura.

    I valori letterali numerici definiti dall’utente possono essere definiti fornendo un modulo il cui nome inizia con NumericLiteral e che definisce determinati metodi ( FromZero , FromOne , ecc.).

    In particolare, è ansible utilizzarlo per fornire una syntax molto più leggibile per chiamare LanguagePrimitives.GenericZero e 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 

    F # ha una caratteristica poco usata chiamata “firma file”. Puoi avere un grande file di implementazione pieno di tipi / metodi / moduli / funzioni pubblici, ma in questo modo puoi hide ed esporre selettivamente quella funzionalità al sequel del programma tramite un file di firma. Cioè, un file di firma agisce come una sorta di schermo / filtro che consente di rendere le quadro “pubbliche a questo file” ma “private al resto del programma”.

    Mi sembra che questa sia una caratteristica piuttosto pericolosa sulla piattaforma .Net, perché l’unico altro / strumento precedente che hai per questo tipo di incapsulamento sono gli assembly. Se hai un piccolo componente con alcuni tipi correlati che vogliono essere in grado di vedere i rispettivi dettagli interni, ma non vuoi che quei tipi abbiano tutti quei bit pubblici a tutti , cosa puoi fare? Bene, puoi fare due cose:

    1. Puoi mettere quel componente in un assieme separato e rendere i membri che quei tipi condividono essere “interni”, e rendere la parte ristretta che vuoi che tutti gli altri vedano essere “pubblica”, o
    2. Contrassegni solo le cose interne “interne” ma lasci questi tipi nel tuo gigantesco assemblaggio e speriamo che tutto l’altro codice nell’assembly scelga di non chiamare quei membri che erano solo contrassegnati come “interni” perché un altro tipo doveva vederlo .

    Nella mia esperienza, su progetti software di grandi dimensioni, ognuno fa sempre # 2, perché # 1 è un non-starter per vari motivi (le persone non vogliono 50 piccoli assiemi, vogliono 1 o 2 o 3 grandi assiemi, per altri forse- buone ragioni non correlate al punto di incapsulamento che sto sollevando (a parte: tutti parlano di ILMerge ma nessuno la usa)).

    Quindi hai scelto l’opzione # 2. Poi un anno dopo, finalmente decidi di rifattorizzare quel componente, e scopri che nell’ultimo anno, altri 17 posti ora chiamano quel metodo “interno” che in realtà era pensato solo per quell’altro tipo da chiamare, facendolo davvero difficile da calcolare quel po ‘perché ora tutti dipendono da quei dettagli di implementazione. Bummer.

    Il punto è che non esiste un buon modo per creare un ambito / limite di incapsulamento intra-assembly di dimensioni moderate in .Net. Spesso le volte “interne” sono troppo grandi e “private” è troppo piccolo.

    … fino a F #. Con i file di firma F #, puoi creare un ambito di incapsulamento di “questo file di codice sorgente” contrassegnando un sacco di cose come pubblico all’interno del file di implementazione, in modo che tutto l’altro codice nel file possa vederlo e fare festa su di esso, ma poi usare un file di firma per hide tutti i dettagli si aspetta la stretta interfaccia pubblica che il componente espone al resto del mondo. Questo è felice Definisci tre tipi altamente correlati in un unico file, consenti loro di vedere i dettagli dell’implementazione, ma espongono solo le cose veramente pubbliche a tutti gli altri. Vincere!

    I file delle firme non sono forse la caratteristica ideale per i limiti di incapsulamento intra-assembly, ma sono l’ unica caratteristica che conosco, e così mi aggrappo a loro come una zattera di salvataggio nell’oceano.

    TL; DR

    La complessità è il nemico. I confini dell’incapsulamento sono un’arma contro questo nemico. “privato” è una grande arma, ma a volte troppo piccola per essere applicabile, e “interna” è spesso troppo debole perché così tanto codice (intero assemblaggio e tutti gli InternalsVisibleTo) può vedere cose interne. F # offre un ambito più grande di “privato per un tipo” ma più piccolo di “tutto l’assemblaggio”, e questo è molto utile.

    Mi chiedo cosa succede se aggiungi

        

    al tuo file devenv.exe.config? (Utilizzare a proprio rischio.)

    Passando --warnon:1182 al compilatore triggers gli avvisi sulle variabili inutilizzate; i nomi delle variabili che iniziano con il trattino basso sono immuni.

    Le funzioni di confronto generate automaticamente per i tipi di dati algebrici (basate sull’ordinamento lessicografico) sono una caratteristica interessante relativamente sconosciuta; vedere

    http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!548.entry

    per un esempio.

    Sì, F # non ha caratteristiche “nascoste”, ma sicuramente ha un sacco di potenza nel linguaggio semplice. Una caratteristica meno conosciuta della lingua, è dove puoi sostanzialmente abilitare la digitazione anatra nonostante F # sia staticamente tipizzato.

    Vedi questa domanda

    Operatore F # “?”

    per informazioni sull’operatore del punto interrogativo e su come fornisce il meccanismo linguistico di base per creare una funzione simile a “dynamic” in C #.

    Non proprio nascosto , ma come persona non-ML questo mi è sfuggito per un po ‘di tempo:

    La corrispondenza del modello può decomporsi arbitrariamente in profondità nelle strutture di dati.

    Ecco un esempio di tupla annidato [incredibilmente arbitrario]; questo funziona su liste o unioni o su qualsiasi combinazione di valori annidati:

     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 ) 

    L’uso di F # come linguaggio di scripting dell’utilità può essere sottostimato. Gli appassionati di F # tendono ad essere quants. A volte vuoi qualcosa di backup dei tuoi MP3 (o dozzine di server di database) che è un po ‘più robusto del batch. Ho cercato un sostituto moderno per jscript / vbscript. Ultimamente, ho usato IronPython, ma F # potrebbe essere più completo e l’interazione con .NET è meno ingombrante.

    Mi piacciono le funzioni al curry per il valore di intrattenimento. Mostra una funzione al curry ad un puro programma procedurale / OOP per almeno tre WTF. A partire da questo è un brutto modo di ottenere convertitori F #, anche se 🙂

    Gli operatori raggruppati su tipi generici possono avere diversi vincoli generici:

     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) 

    Non ci sono funzioni nascoste, perché F # è in modalità progettazione. Tutto ciò che abbiamo è un’anteprima tecnica, che cambia ogni due mesi.

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