Tessitura di codice byte e macro Lisp


11

Ho letto delle biblioteche che le persone hanno scritto per linguaggi come Java e C # che fanno uso della tessitura del codice byte per fare cose come intercettare chiamate di funzioni, inserire codice di registrazione, ecc. Ho anche letto su macro Lisp / Clojure in un cercare di capire meglio come utilizzarli. Più leggo sulle macro, più sembra che forniscano lo stesso tipo di funzionalità delle librerie di tessitura a codice byte. Per funzionalità intendo la capacità di manipolare il codice in fase di compilazione.

Esempi di librerie che ho esaminato sarebbero AspectJ, PostSharp e Cecil.

C'è qualcosa che si può fare con l'uno e non con l'altro? In realtà risolvono gli stessi problemi o sto confrontando mele e arance?


2
la tessitura del codice byte è una soluzione quando hai bisogno di un linguaggio dinamico ma sei bloccato con un linguaggio tipicamente statico
kevin cline

2
@kevincline stai davvero cercando di iniziare questa vecchia battaglia?
Jonathan Henson,

Risposte:


10

La tessitura del codice byte e le macro sono due cose diverse.

La tessitura del codice byte è un modo per intercettare le chiamate di funzione, in modo da poter iniettare una sorta di funzionalità (generalmente un problema trasversale come la registrazione) in una chiamata di funzione, prima o dopo l'esecuzione della funzione. La tessitura del codice byte viene eseguita a livello di codice byte, il che significa che si verifica dopo la compilazione. La funzione stessa non è interessata. Questa è una delle tecniche utilizzate dalla programmazione orientata agli aspetti .

Le macro sono un modo per estendere la sintassi di una lingua. Nella sua forma più semplice, una macro è semplicemente un modo per registrare le sequenze di tasti e quindi riprodurle utilizzando un tasto di scelta rapida. Le macro linguistiche funzionano in modo simile; una parola chiave o altro costrutto di sintassi sostituisce una sorta di espansione macro. Questo è semplificato, ovviamente; un esempio migliore di una macro specifica per Lisp può essere trovato qui .


+1 per menzionare che questo è un modo chiave per implementare AOP.
Jonathan Henson,

E le transazioni ... non dimentichiamoci delle transazioni.
Jonathan Henson,

3
Le macro LISP non assomigliano a "un modo per registrare i tasti".
Kevin Cline,

1
Bene alcuni concetti fondamentali mancano alla risposta IMO, quelli potrebbero essere: AST, riflessione, metacircolarità.
AndreasScheinert,

2
@AndreasScheinert: l'OP non ha chiesto nulla di tutto ciò. Questa non è una tesi; è solo una risposta alla domanda del PO.
Robert Harvey,

5

Sebbene possano essere utilizzati allo stesso fine, le macro LISP sono abbastanza diverse dai plugin di tessitura Java con codice byte. Le macro LISP estendono la sintassi LISP a livello di codice sorgente LISP. Poiché le macro LISP sono scritte allo stesso livello di altri codici LISP, sono una funzione di linguaggio comunemente usata.

I plugin di tessitura Java con codice byte funzionano a livello di JVM. Mentre molti programmatori Java possono usare plugin di tessitura di codice byte scritti da altri, pochissimi programmatori Java scrivono i propri plugin di tessitura di codice byte.

Parte del lavoro svolto dai plug-in del compilatore Java viene eseguito molto facilmente in linguaggi dinamici. L'intercettazione di chiamate di funzione è particolarmente semplice.


Comprendo le differenze tecniche tra i due. Stavo provando a guardare la domanda da un punto di vista di alto livello. Entrambi gli strumenti possono manipolare il codice per raggiungere gli stessi obiettivi? Ci sono problemi che le macro non possono risolvere come la manipolazione di bytecode (in modo sano ed economico)? Questo è più quello che stavo cercando.
mortalapeman

@mortalapeman: le manipolazioni possibili in Java e C # tramite modifica del codice byte possono essere eseguite direttamente in lingue come Lisp, Ruby, Python, Lua, Javascript ... È presumibilmente possibile fare tutto ciò che una macro LISP può fare tramite byte manipolazione del codice, ma in pratica ciò non accade.
Kevin Cline,

4

Le macro Lisp funzionano a livello di codice sorgente. Se avvolgi una macro attorno a un pezzo di codice, puoi fare molte cose. Compreso l'analisi del codice sorgente, l'inserimento del codice, la riscrittura del codice, ecc.

Se si desidera modificare le chiamate di funzione, Lisp di solito utilizza due meccanismi:

  • simboli di associazione tardiva. È possibile modificare la funzione associata a un simbolo. Ogni chiamata di funzione che passa attraverso un simbolo, quindi utilizza la nuova funzione.

  • Le implementazioni di Lisp a volte forniscono una funzionalità chiamata "consulenza". Ciò consente di eseguire il codice prima, dopo o intorno alle chiamate. Ad esempio in LispWorks: Consigli .

In questo modo è possibile intercettare le chiamate senza manipolazione del codice di basso livello.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.