Elisir - Macro

Le macro sono una delle funzionalità più avanzate e potenti di Elixir. Come per tutte le funzionalità avanzate di qualsiasi lingua, le macro dovrebbero essere utilizzate con parsimonia. Consentono di eseguire potenti trasformazioni del codice in fase di compilazione. Ora capiremo cosa sono le macro e come usarle in breve.

Citazione

Prima di iniziare a parlare di macro, diamo un'occhiata agli interni di Elixir. Un programma Elixir può essere rappresentato dalle proprie strutture dati. L'elemento costitutivo di un programma Elixir è una tupla con tre elementi. Ad esempio, la chiamata di funzione sum (1, 2, 3) è rappresentata internamente come -

{:sum, [], [1, 2, 3]}

Il primo elemento è il nome della funzione, il secondo è un elenco di parole chiave contenente metadati e il terzo è l'elenco degli argomenti. Puoi ottenerlo come output nella shell iex se scrivi quanto segue:

quote do: sum(1, 2, 3)

Anche gli operatori sono rappresentati come tali tuple. Anche le variabili sono rappresentate usando tali terzine, tranne per il fatto che l'ultimo elemento è un atomo, invece di una lista. Quando si citano espressioni più complesse, possiamo vedere che il codice è rappresentato in tali tuple, che sono spesso annidate l'una nell'altra in una struttura simile a un albero. Molte lingue chiamerebbero tali rappresentazioni unAbstract Syntax Tree (AST). Elixir chiama queste espressioni citate.

Unquote

Ora che possiamo recuperare la struttura interna del nostro codice, come la modifichiamo? Per iniettare nuovo codice o valori, usiamounquote. Quando deselezioniamo un'espressione, questa verrà valutata e iniettata nell'AST. Consideriamo un esempio (nella shell iex) per comprendere il concetto:

num = 25

quote do: sum(15, num)

quote do: sum(15, unquote(num))

Quando il programma di cui sopra viene eseguito, produce il seguente risultato:

{:sum, [], [15, {:num, [], Elixir}]}
{:sum, [], [15, 25]}

Nell'esempio per l'espressione di virgolette, non ha sostituito automaticamente num con 25. Dobbiamo deselezionare questa variabile se vogliamo modificare l'AST.

Macro

Quindi, ora che abbiamo familiarità con citazione e non citazione, possiamo esplorare la metaprogrammazione in Elixir usando le macro.

In termini più semplici, le macro sono funzioni speciali progettate per restituire un'espressione tra virgolette che verrà inserita nel codice dell'applicazione. Immagina che la macro venga sostituita con l'espressione tra virgolette anziché essere chiamata come una funzione. Con le macro abbiamo tutto il necessario per estendere Elixir e aggiungere dinamicamente codice alle nostre applicazioni

Cerchiamo di implementare se non come macro. Inizieremo definendo la macro utilizzando ildefmacromacro. Ricorda che la nostra macro deve restituire un'espressione tra virgolette.

defmodule OurMacro do
   defmacro unless(expr, do: block) do
      quote do
         if !unquote(expr), do: unquote(block)
      end
   end
end

require OurMacro

OurMacro.unless true, do: IO.puts "True Expression"

OurMacro.unless false, do: IO.puts "False expression"

Quando il programma di cui sopra viene eseguito, produce il seguente risultato:

False expression

Quello che sta accadendo qui è il nostro codice è stato sostituito dal codice citato restituito dal meno che macro. Abbiamo rimosso le virgolette dall'espressione per valutarla nel contesto corrente e abbiamo anche rimosso le virgolette dal blocco do per eseguirlo nel suo contesto. Questo esempio ci mostra la metaprogrammazione utilizzando le macro in elisir.

Le macro possono essere utilizzate in attività molto più complesse, ma dovrebbero essere utilizzate con parsimonia. Questo perché la metaprogrammazione in generale è considerata una cattiva pratica e dovrebbe essere utilizzata solo quando necessario.