Ty

Typespec in Elixir

1 esercizio

Informazioni su Typespec

Elixir è un linguaggio a tipizzazione dinamica: non fornisce controlli di tipo a tempo di compilazione. Tuttavia, le specifiche di tipo possono comunque essere utili perché:

  • Servono come documentazione.
  • Possono essere usate da strumenti di analisi statica come Dialyzer per trovare possibili bug.

Una specifica di tipo può essere aggiunta a una funzione usando l'attributo di modulo @spec subito prima della definizione della funzione.

@spec longer_than?(String.t(), non_neg_integer()) :: boolean()
def longer_than?(string, length), do: String.length(string) > length

I tipi

Espressioni consentite in una specifica di tipo:

  • Tipi di base, per esempio:

    • boolean()
    • integer(), non_neg_integer(), pos_integer(), float()
    • list()
    • map()
    • any()
  • Un'unione di tipi:

    • ad es. integer() | list(integer())
  • Tipi parametrizzati:

    • ad es. list(integer()), una lista di interi
    • ad es. %{age: integer()}, una mappa con un valore intero sotto la chiave :age
  • Tipi remoti (definiti in qualche modulo), per esempio:

  • Letterali, per esempio:

    • %{}, una mappa vuota
    • [], una lista vuota (ma [any()] è una lista non vuota)
    • ad es. :ok, un atomo letterale
  • Tipi specializzati integrati, per esempio:

    • char(), un intero nell'intervallo 0..0x10FFFF
    • charlist(), una lista di caratteri
    • keyword(), una lista di tuple di due elementi, dove il primo elemento è un atomo
  • Tipi personalizzati

Un elenco completo di tutti i tipi si trova nella sezione "Typespecs" della documentazione ufficiale.

Dare un nome agli argomenti

Anche gli argomenti nella specifica di tipo possono avere un nome, il che è utile per distinguere più argomenti dello stesso tipo.

@spec to_hex({hue :: integer, saturation :: integer, lightness :: integer}) :: String.t()

Tipi personalizzati

I tipi personalizzati si possono definire usando uno dei tre attributi di modulo:

  • @type, definisce un tipo pubblico
  • @typep, definisce un tipo privato
  • @opaque, definisce un tipo pubblico la cui struttura è privata
@type color :: {hue :: integer, saturation :: integer, lightness :: integer}

@spec to_hex(color()) :: String.t()

String.t() vs binary() vs string()

String.t() è il tipo corretto da usare per le stringhe di Elixir, che sono binari codificati in UTF-8. Tecnicamente, String.t() è definito come un binary(), e i due tipi sono equivalenti per gli strumenti di analisi, ma String.t() è la scelta che rivela meglio l'intenzione quando si documentano funzioni che lavorano con le stringhe di Elixir.

D'altra parte, string() è un tipo diverso. È una stringa di Erlang, nota in Elixir come charlist. Il tipo string() va evitato nelle specifiche di tipo; al suo posto va usato charlist().

Dialyzer

Dialyzer è uno strumento di analisi statica che può individuare problemi come gli errori di tipo nel codice Erlang ed Elixir. Il modo più semplice per usare Dialyzer in un progetto Elixir è con Dialyxir.

Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda

Impara Typespec