Geralmente, a parte mais difícil na escrita de uma macro é a determinação das expressões Lisp que quando avaliadas produzem uma nova expressão Lisp que realiza o nosso objectivo. Para simplificar esta tarefa é usual utilizarem-se caracteres especiais que, à semelhança da plica (quote) e do cardinal-plica (function) são transformados na leitura para outras expressões. Cada um dos caracteres especiais possui uma função Lisp associada que é avaliada quando a linguagem, durante a leitura das expressões, encontra um desses caracteres. Essa função Lisp pode então realizar mais leituras e retornar o que achar mais conveniente.
Estes caracteres especiais são designados caracteres de macro pois eles são transformados (são expandidos) na leitura em outras expressões, um pouco à imagem do que acontecia com as macros. A diferenção está no instante em que a expansão ocorre. Uma macro é expandida em tempo de compilação (ou, em algumas implementações de Lisp, em tempo de execução). Um carácter de macro é expandido na leitura de expressões.
Qualquer carácter pode ser considerado especial, bastando, para isso, usar a função set-macro-caracter que recebe um carácter e uma função a aplicar sempre que o carácter for lido. A função a aplicar deve possuir dois parâmetros que receberão, o primeiro, o local donde o Lisp estava a ler (terminal, ficheiro, etc) para que a função possa continuar a leitura do mesmo sítio, e o segundo, o próprio carácter de macro.
Para se indicar um carácter em Lisp é
necessário precedê-lo dos caracteres ``#\
''. Por exemplo, o carácter $ é indicado por ``#\$
''.
Como já é sabido, se não se incluíssem os caracteres
``#\
'', o Lisp consideraria o objecto lido como um símbolo
e não como um carácter.
Para se compreender a utilização dos caracteres de macro, podemos admitir que não existia o carácter de plica e que pretendíamos defini-lo. A expressão 'ola representa, como sabemos, (quote ola), logo a função que seria invocada quando se encontrasse a plica necessitaria de ler o objecto que estava após a plica (usando a função read) e construiria uma lista com o símbolo quote à cabeça e o objecto lido no fim, ou seja:
(defun plica (canal-leitura caracter) (list (quote quote) (read canal-leitura)))> (set-macro-character #´ (function plica)) T > 'ola OLA
A linguagem Lisp possui, previamente definidos, vários caracteres de macro. A plica é um deles, o ponto e vírgula (que representa um comentário) é outro, etc. Alguns dos caracteres de macro são precedidos por um carácter especial, considerado o carácter de despacho, permitindo aumentar o número de possíveis caracteres de macro sem reduzir o número de caracteres normais utilizáveis. O carácter de despacho mais usado é o cardinal, mas pode ser qualquer outro. Como exemplos destes caracteres de macro com despacho temos o cardinal-plica para indicar funções, o cardinal-barra para indicar caracteres, etc.
De todos os caracteres de macro, aqueles que são particularmente úteis para a escrita de macros são o plica para trás (`--backquote), a vírgula (,--comma) e o vírgula-arroba (,@--comma-at).
O backquote indica ao avaliador que não deve avaliar uma expressão excepto quando for indicado em contrário. Quando usado isoladamente, o backquote funciona exactamente como o quote. No entanto, a sua combinação com o comma e o comma-at permite simplificar imenso a escrita de expressões complexas. O comma só pode ser utilizado numa expressão (uma lista, tipicamente) precedida do backquote, e informa o avaliador que a expressão que se segue é para avaliar e o seu resultado inserido na lista. O comma-at é idêntico mas o resultado da avaliação tem de ser uma lista cujos elementos são inseridos.
A título de exemplo, temos:
> `((+ 1 2) ,(+ 1 2) (list 1 2) ,(list 1 2) ,@(list 1 2)) ((+ 1 2) 3 (LIST 1 2) (1 2) 1 2)