Clojure: Macros e Extensibilidade
Macros permitem transformar uma expressão qualquer em código Clojure válido, desta forma você pode estender a linguagem para que ela se adeque às suas necessidades. - Traduzido de Clojure For the Brave and True
Vamos a um exemplo:
No trecho de código acima, definimos a função "backwards" utilizando defmacro e a executamos passando como argumentos os valores ("backwards" " am" "I" str).
Ela irá inverter os parâmetros recebidos e executar a função str concatenando todos os valores recebidos, desta forma temos como retorno a string "I am backwards".
E porque isso é tão legal?
Porque várias funções presentes no clojure foram implementadas usando esta mesma abordagem.
when é uma função que a partir de uma condição lógica executa uma sequência de passos, mas quando esta função é lida ou macroexpandida ela se torna o código abaixo.
"A linguagem Lisp original, como definida por John McCarthy em seu ensaio “Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I” (McCarthy 1960), definiu toda a linguagem em termos de apenas sete funções e duas formas especiais. : atom, car, cdr, cond, cons, eq, quote, lambda e label. Através da composição dessas nove formas, McCarthy foi capaz de descrever toda a computação de uma forma que nos deixa sem fôlego." - Traduzido de The Joy of Clojure, 2nd edition
Já pensou como seria definir uma linguagem utilizando apenas 7 funções e duas formas especiais?
Como Clojure é um dialeto de lisp, também conseguimos estender a linguagem da forma que precisarmos, tanto é verdade que a própria linguagem criou seu framework de testes nativo o clojure.test utilizando macros.
Legal né?