2012-02-21 14 views
7

Come è possibile utilizzare la parola -spec in erlang? Per favore, dammi un'idea dell'uso efficiente di questa parola. Does è solo a scopo di documentazione?Specifiche per le funzioni: -spec. Uso efficiente

Sto provando ad applicare un vincolo per funzionare nel modulo per specifica del tipo di funzione utilizzando -spec, ma non ho funzionato. Non sono state applicate restrizioni.

risposta

18

-spec gli attributi sono effettivamente trattati dal compilatore e dal sistema di runtime come documentazione. Non è possibile aggiungere alcuna "caratteristica eseguibile" al proprio codice utilizzandoli e lo stesso vale per gli attributi -type e -opaque.

Tuttavia, essi sono utili come:

  • Documentazione: hanno usato per Edoc per generare tutte le diverse forme di documentazione per il codice. Gli attributi -spec sono firme di funzioni che, a seconda dell'impegno che si mettono in esse, possono rendere il codice più comprensibile e mantenibile. Supponiamo che la tua struttura dati preferita questo mese sia dict(). Considerare il seguente codice:

    my_function(SomeArg, SomeOtherArg, Dict) -> 
        ... 
        dict:find(SomeKey, Dict) 
        ... 
    

    La variabile che viene utilizzata come dict è stata denominata come tale. Ma diciamo che si ha il seguente frammento:

    my_other_function(NamesDict, PlacesDict) -> 
        ... 
        R1 = my_function(A, B, NamesDict), 
        ... 
        R2 = my_function(C, D, PlacesDict), 
    ... 
    

    Cercando di tenere il passo con questo potrebbe presto portare a codice che si ripete questo suffisso Dict. Inoltre, potresti non voler nemmeno ricordare nel contesto di my_other_function che i due argomenti sono dict(). Così, invece si potrebbe desiderare di fare questo:

    -spec my_other_function(dict(), dict()) -> atom(). 
    
    my_other_function(Names, Places) -> 
        ... 
        R1 = my_function(A, B, Names), 
        ... 
        R2 = my_function(C, D, Places), 
        ... 
    

    Ora è chiaro che questi argomenti dovrebbero essere dict() per la funzione di lavorare e speriamo tutti saranno in grado di capire che, senza andare in profondità nel codice.Supponiamo che tu stia utilizzando questo Namedict() in altri luoghi e memorizzi alcune informazioni particolari esposte con API diverse. Allora è un candidato perfetto per una dichiarazione -type:

    -type names() :: dict(). 
    
    -spec my_other_function(names(), places()) -> atom(). 
    
    my_other_function(Names, Places) -> 
        ... 
        R1 = my_function(A, B, Names), 
        ... 
        R2 = my_function(C, D, Places), 
        ... 
    

    Se qualcun altro fa uso frequente di questa particolare struttura dati si consiglia di esportarlo anche:

    -module(my_module). 
    
    -export_type([names/0]). 
    
    -type names() :: dict(). 
    

    Altri moduli possono ora fare riferimento a questo particolare struttura dei dati:

    -module(my_other_module). 
    
    -record(my_state, {names :: my_module:names(), 
            ...}). 
    

    Infine, se si preferisce altro sviluppatore di non esaminare questa struttura dati in alcun modo nella loro moduli, è possibile de Chiaro come -opaque. Ancora una volta, questo è un "suggerimento amichevole", così come tutto il resto della roba fino ad ora. O è...?

  • rilevamento di discrepanza: Se si prende il tempo di utilizzare -specs e -types si sarebbe molto simile a che questi sono tenuti fino ad oggi. È risaputo che nessuno mantiene aggiornata la documentazione se non c'è nessuno che la guarda! Fortunatamente, Dialyzer sta guardando. Dialyzer puòcheck che in tutte le chiamate a my_function() gli argomenti sono dict() (può farlo anche senza le tue annotazioni -spec ma è così facile se ci sono anche lì) e urlare un sanguinoso omicidio se lo chiami con qualcos'altro. Può inoltre tenere traccia di questi tipi esportati e persino segnalare violazioni di opacità. Quindi non è "solo documentazione".

  • generazione Testcase: corretta possibile utilizzare le -spec e -type definizioni per controllare automaticamente le funzioni di casi di test casuali. E 'in grado di rendere casi di test casuali anche da dichiarazioni come questa:

    -type int_tree() :: {node, integer(), tree(), tree()} | nil. 
    
  • Il nuovo modo di specificare una serie di callback per un comportamento è quello di utilizzare il familiare -spec sintassi. Compilatore, Dialyzer e possibilmente altri strumenti possono utilizzare queste informazioni per verificare l'implementazione di un comportamento. Scopri di più su OTP comportamenti code e here

Read more here.

+0

Grazie per la risposta dettagliata.Il '-opaque' equivale a' -type' senza la dichiarazione '-export_type'? – egor7

+0

No, è ancora necessario esportare tutti i tipi '-opaque' che si dichiarano. – aronisstav

8

-spec 's per le funzioni sono le specifiche che ha più luoghi dove si aiutano:

  • Essi agiscono come documentazione della funzione. La generazione di EDoc estrae le specifiche e le rende disponibili nella documentazione.
  • Sono una specifica per il dializzatore. Quando il dializzatore esegue, utilizzerà le specifiche per determinare se il codice è sbagliato in qualche modo. Cioè, se le specifiche sono sbagliate - e in alcuni casi aiuterà il sistema a capire esattamente perché anche il codice è sbagliato.
  • Sono uno strumento prezioso nelle specifiche dei comportamenti. C'è una nuova parola chiave -callback che può essere usata per fare ciò per le API comportamentali.
  • Sono utili per la costruzione di un tipo di scheletro di come il programma si adatta e da dove provengono i dati.
  • Insieme ai cugini -type e -opaque è possibile imporre determinati tipi di opaco a parti di codice. Ciò significa che non ti è permesso vedere la rappresentazione interna su un livello di verifica statico. Questo può a sua volta aiutare a guidare il codice modularizzato in quanto non ti è permesso di accoppiare strettamente pezzi di codice.
+0

Grazie, ma aiutatemi con l'ultima dichiarazione per favore. Qual è la differenza tra '-type' e' -opaque'. Potremmo usare '-type' solo nel modulo, e se vogliamo che diventi visibile, dobbiamo fornire la parola' -export_type'. Si tratta degli stessi termini '-type' e' -opaque' se non usiamo la parola '-export_type'? – egor7

+0

Puoi per favore indicare alcuni documenti su questa nuova parola chiave '-callback'? –

+0

Ivan, vedi http://www.erlang.org/doc/design_principles/spec_proc.html#id72728 per esempio. Mi diverto molto a guardare tutti i documenti di erlang per trovare una cosa o l'altra. Sembra che i ragazzi di Erlang scrivano tutti i documenti preziosi alla fine di quasi tutti i documenti - uomini, principi di sistema, referencese. Quindi se vuoi iniziare a scrivere e capire i programmi di erlang dovresti leggere i documenti dal basso verso l'alto) – egor7

Problemi correlati