Tecelagem de código de bytes vs macros Lisp

11

Eu tenho lido sobre as bibliotecas que as pessoas escreveram para linguagens como Java e C # que utilizam tecelagem de código de bytes para fazer coisas como interceptar chamadas de função, inserir código de log etc. etc. Também estive lendo nas macros Lisp / Clojure tente entender melhor como utilizá-los. Quanto mais eu leio sobre macros, mais elas parecem oferecer o mesmo tipo de funcionalidade que as bibliotecas de tecelagem de código de bytes. Por funcionalidade, quero dizer a capacidade de manipular código em tempo de compilação.

Exemplos de bibliotecas que estive pesquisando seriam AspectJ, PostSharp e Cecil.

Existe algo que possa ser feito com um e não com o outro? Eles realmente resolvem os mesmos problemas ou estou comparando maçãs e laranjas?

mortalapeman
fonte
2
tecelagem código byte é um trabalho em torno de quando você precisa de uma linguagem dinâmica, mas está preso com uma linguagem de tipagem estática
kevin Cline
2
@kevincline você está tentando seriamente começar essa luta antiga?
perfil completo de Jonathan Henson

Respostas:

10

A tecelagem de códigos de bytes e as macros são duas coisas diferentes.

A tecelagem de código de bytes é uma maneira de interceptar chamadas de função, para que você possa injetar algum tipo de funcionalidade (geralmente uma preocupação transversal como o log) em uma chamada de função, antes ou depois da execução da função. A tecelagem do código de bytes é feita no nível do código de bytes, o que significa que ocorre após a compilação. A função em si não é afetada. Essa é uma das técnicas que a Programação Orientada a Aspectos usa.

Macros são uma maneira de estender a sintaxe de um idioma. Na sua forma mais simples, uma macro é simplesmente uma maneira de gravar pressionamentos de teclas e reproduzi-los usando uma tecla de atalho. Macros de linguagem funcionam de maneira semelhante; uma palavra-chave ou outra construção de sintaxe substitui algum tipo de expansão de macro. Isso é simplificado demais, é claro; um exemplo melhor de uma macro específica para Lisp pode ser encontrada aqui .

Robert Harvey
fonte
+1 por mencionar que essa é uma maneira essencial de implementar a AOP.
Jonathan Henson
E transações ... não vamos esquecer transações.
perfil completo de Jonathan Henson
3
As macros LISP não são nada como 'uma maneira de gravar pressionamentos de tecla'.
Kevin Cline
1
Bem, faltam alguns conceitos fundamentais para a resposta IMO, que podem ser: AST, reflexão, Metacircularidade.
precisa saber é o seguinte
2
@AndreasScheinert: O OP não perguntou sobre nada disso. Esta não é uma dissertação; é apenas uma resposta para a pergunta do OP.
Robert Harvey
5

Embora possam ser usadas para o mesmo fim, as macros LISP são bem diferentes dos plug-ins de tecelagem de código de bytes Java. As macros LISP estendem a sintaxe LISP no nível do código-fonte LISP. Como as macros LISP são escritas no mesmo nível que outro código LISP, elas são um recurso de idioma usado com frequência.

Os plug-ins de tecelagem de código de bytes Java operam no nível da JVM. Enquanto muitos programadores Java podem usar plugins de tecelagem de código de bytes criados por outros, muito poucos programadores Java escrevem seus próprios plugins de tecelagem de código de bytes.

Parte do trabalho realizado pelos plug-ins de compilador Java é muito fácil em linguagens dinâmicas. A interceptação de chamada de função é particularmente simples.

Kevin Cline
fonte
Eu entendo as diferenças técnicas entre os dois. Eu estava tentando olhar para a pergunta de um ponto de vista de alto nível. As duas ferramentas podem manipular o código para alcançar os mesmos objetivos? Existem problemas que as macros não conseguem resolver que a manipulação do bytecode pode (de maneira sã e econômica)? Era isso o que eu estava procurando.
mortalapeman
@ mortalapeman: as manipulações possíveis em Java e C # via modificação de código de bytes podem ser feitas diretamente em linguagens como Lisp, Ruby, Python, Lua, Javascript ... Presumivelmente, é possível fazer tudo o que uma macro LISP pode fazer via byte manipulação de código, mas na prática isso não acontece.
Kevin Cline
4

As macros Lisp estão operando no nível do código-fonte. Se você envolver alguma macro em torno de um pedaço de código, poderá fazer várias coisas. Incluindo analisar o código fonte, inserir código, reescrever código, etc.

Se você deseja modificar as chamadas de função, o Lisp geralmente usa dois mecanismos:

  • símbolos de ligação tardia. Você pode modificar a função vinculada a um símbolo. Toda chamada de função que passa por um símbolo e usa a nova função.

  • As implementações do Lisp às vezes fornecem um recurso chamado 'conselho'. Isso permite executar o código antes, depois ou próximo das chamadas. Por exemplo, no LispWorks: Conselhos .

Assim, você pode interceptar chamadas sem manipulação de código de baixo nível.

Rainer Joswig
fonte