Tracce
/
Elixir
Elixir
/
Programma
/
Protocolli
Pr

Protocolli in Elixir

4 esercizi

Informazioni su Protocolli

I protocolli sono:

  • Un meccanismo per ottenere il polimorfismo.
  • Definiti con defprotocol.
  • Implementati per uno specifico tipo di dato con defimpl.

Un grande punto di forza dei protocolli è che l'implementazione di un protocollo per uno specifico tipo di dato non deve essere inclusa nella definizione del tipo di dato né in quella del protocollo. Questo permette di scrivere librerie che gli utenti possono estendere facilmente per lavorare con i propri tipi di dato personalizzati, senza dover modificare la libreria.

Implementazione

È possibile implementare i protocolli per tutti i tipi di Elixir: Tuple, Atom, List, BitString, Integer, Float, Function, PID, Map, Port, Reference, Any e le struct.

I protocolli si possono implementare per più tipi contemporaneamente:

defimpl Reversible, for: [Map, List] do
  def reverse(term) do
    Enum.reverse(term)
  end
end

Quando si implementa un protocollo per una struct direttamente all'interno di un modulo che definisce la struct, l'argomento :for si può omettere:

defmodule ShoppingCart do
  defstruct [:items]

  defimpl Reversible do
    def reverse(shopping_cart) do
      Enum.reverse(shopping_cart)
    end
  end
end

Fallback su Any

Per impostazione predefinita, chiamare un protocollo per un tipo di dato per cui non è stato implementato genera un errore Protocol.UndefinedError:

to_string({})
# => ** (Protocol.UndefinedError) protocol String.Chars not implemented for {} of type Tuple
#        (elixir 1.10.3) lib/string/chars.ex:3: String.Chars.impl_for!/1
#        (elixir 1.10.3) lib/string/chars.ex:22: String.Chars.to_string/1

È possibile evitarlo fornendo un'implementazione di fallback che verrà usata in questo caso. Per farlo, imposta l'attributo di modulo @fallback_to_any su true quando definisci il protocollo e scrivi un'implementazione per il tipo Any:

defprotocol Reversible do
  @fallback_to_any true
  def reverse(term)
end

defimpl Reversible, for: Any do
  def reverse(term) do
    term
  end
end

Tieni presente che nella maggior parte dei casi è preferibile generare un errore, perché è difficile fare un'ipotesi ragionevole su un protocollo per tutti i tipi di dato.

Protocolli integrati degni di nota

  • Enumerable: le funzioni dei moduli Enum e Stream funzionano con i tipi di dato che implementano questo protocollo.
  • Collectable: la funzione Enum.into/2 usa questo protocollo per inserire un enumerable in una collezione.
  • Inspect: puoi implementare questo protocollo per cambiare il modo in cui Kernel.inspect/2 rappresenta come stringa uno specifico tipo di dato.
  • String.Chars: puoi implementare questo protocollo per cambiare il modo in cui Kernel.to_string/1 rappresenta come stringa uno specifico tipo di dato.
Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda

Impara Protocolli

La pratica è bloccata

Sblocca un altro esercizio per esercitarti su Protocolli