2014-06-18 20 views
12

Ogni programmatore Common Lisp sa che le macro sono uno strumento potente. Le macro comuni Lisp sono state utilizzate, tra le altre cose, per aggiungere l'orientamento dell'oggetto sopra Lisp senza cambiando le specifiche della lingua; read-macros sono un altro costrutto con funzionalità di mind bending.Confronto di macro Common Lisp e funzionalità di metaprogrammazione Forth

Un altro programma che consente la meta-programmazione è Forth. Forth lo fa in un modo leggermente diverso, usando "parole" e "genera parole".

Mi piacerebbe sapere, da qualcuno che si è dilettato in entrambe le lingue, se i comuni macro lisp e avanti sono comparabili in larghezza/potenza: c'è qualcosa che puoi fare con il primo che non puoi fare con quest'ultimo ? O vice versa?

Naturalmente, non sto parlando della completezza di Turing delle due lingue: sto parlando delle funzionalità di metaprogramming. C è completo per Turing, ma solo un pazzo affermerebbe che le macro C sono comparabili in termini di potenza a quelle Common Lisp.

+2

Questo è molto più specifico della versione precedente, [Lisp e Forth macro [[in attesa \]] (http://stackoverflow.com/q/24272856/1281433), che è buono.Certo, ora * quella * domanda ha riaperto i voti, e questo ha un voto ravvicinato, quindi c'è una certa confusione su quale di questi dovrebbe effettivamente rimanere aperto. È molto più chiaro ciò che stai cercando in questa domanda, ma è ancora probabilmente fuori tema, perché ["la domanda di confronto è inadatta per \ [Stack Overflow \], perché non ci sono limiti alle risposte che possono essere postate loro ".] (http://meta.stackoverflow.com/q/251328/1281433). –

+3

Il motivo di chiusura ** troppo ampio ** si applica qui: "Ci sono * troppe risposte possibili *, o le risposte positive sarebbero troppo lunghe per questo formato." Questa non è affatto una brutta domanda **; non è particolarmente adatto per Stack Overflow. Per esempio, questa domanda potrebbe essere ottima in comp.lang.lisp. –

+1

La sottoregione particolare, "c'è qualcosa che puoi fare con la prima che non puoi fare con quest'ultima? O viceversa?" è probabilmente il più specifico qui. Potrebbe ancora ammettere troppe risposte, ma se c'è qualcosa che si può fare a differenza dell'altro, è probabilmente possibile dare una risposta relativamente canonica. –

risposta

7

Dal mio punto di vista, le macro Common Lisp sono simili a quelle del . (In realtà, sono più simili alle macro lettore Lisp.)

  • Sono entrambi macro procedurali, vale a dire in grado di utilizzare tutta la potenza del linguaggio.

  • Entrambi hanno accesso all'ingresso del codice sorgente.

  • Entrambi possono emettere qualsiasi cosa sia possibile esprimere nella lingua. (Es un'estensione orientata agli oggetti in Lisp, o costrutti di controllo di flusso di base in avanti.)

La differenza principale, forse, sarebbe che Forth "macro" input sono stringhe di caratteri, mentre le macro Lisp operano su albero di parsing.

+3

Le macro Lisp funzionano con le espressioni S, che suppongo potrebbero sembrare alberi di analisi per non-Lisper, ma comunque. Cito questa distinzione perché in quasi tutti i dialetti Lisp, la fase di lettura viene prima della fase di compilazione, e così i Lisper vedono il codice _as_ dati durante la scrittura di macro. Yay homoiconicity! (Tu sai chiaramente tutto questo dato che [common-lisp] è il top tag per te, ma sento che anche gli altri lettori qui dovrebbero capire la differenza.) –

2

Scusate se la discussione qui sotto potrebbe sembrare un po 'vaga, ma c'è troppo da dire.

Ho solo conoscenze teoriche di Lisp, non le mani.

Dall'altro lato, Forth potrebbe avere (ma il normale Forth non ha) una metaprogrammazione completa all'interno della lingua. Ma la metaprogrammazione è contemplata e possibile ma senza una sintassi coerente. Penso che lo stesso accada in Lisp.

Ho implementato una soluzione molto pulita che include questa possibilità in un piccolo paradigma del linguaggio simile a Forth. Per avere metaprogramming dovremmo essere in grado di riferirci a ciò che scriviamo. Così, quando scriviamo un programma da eseguire immediatelly come:

bread eat 

dovremmo essere in grado anche di fare riferimento alla stessa frase con l'intento, invece di eseguirlo per conservarlo per riferimento futuro. Ciò potrebbe essere fatto scrivendo per es.

{ bread eat } 

La frase sopra potrebbe avere come conseguenza di lasciare l'oggetto creato nello stack. Ma come abbiamo creato una nuova parola come { e } abbiamo il diritto di fare riferimento anche a quello.

Quindi, potremmo piace fare riferimento a:

{ bread 

Come potremmo fare riferimento a questo? Una sintassi provvisoria è: {{ { bread }}.

Se diamo il nome XXX alla frase precedente potremmo scrivere la frase iniziale:

XXX eat } 

e la frase di cui sopra dovrebbe funzionare correttamente nel lasciare sullo stack i

{ bread eat } 

Come Non so se quello che dico è esattamente ciò che stai cercando, basti dire che con il ragionamento di cui sopra e la loro implementazione all'interno di Forth ogni parola ottiene un livello di esecuzione e che definisce qual è il livello di metaprogrammazione della parola.

Ovviamente, abbiamo il primo livello di infinito e ogni livello successivo. Quindi i livelli di esecuzione sono basati sull'infinito matematico.

Ho implementato il suddetto all'interno di una sorta di Forth e al primo livello (sotto infinito) tutto funziona senza intoppi. Così, per esempio un sono in grado di cambiare la sintassi di:

{ bread eat } { tomatos eat } x 3 = if 

in:

{ bread eat | tomatos eat } x 3 = if 

che viene fatto definendo | come } { come muggito:

{{ } { }} "|" define 

o se ti piace meglio come:

2{ } { 2} "|" define 

Il metodo sopra porta all'interno della lingua con una sintassi corretta la meta lingua e lo rende linguaggio.

Quindi, a mio parere, sia Lisp che Forth hanno la possibilità di metaprogrammazione, ma entrambi mancano di tale possibilità come parte integrante della lingua.

Ho ulteriori dettagli su questo su napl.wikispaces.com.

+1

Ho solo conoscenze teoriche di Lisp, non di mani. ... Penso che lo stesso accada in Lisp. –

5

Sono un implementatore di Forth e ho una vasta esperienza in Forth, una mezza dozzina di implementazioni, alcune centinaia di problemi di progettisti. Ho anche fatto una piccola estensione orientata agli oggetti (piccola, cioè una dozzina di linee o giù di lì). La mia esperienza in LISP è molto più a livello di corso, ma penso che sia giusto dire che le strutture di meta-programmazione di LISP sono più sistematiche e, in pratica, più potenti.

È relativamente semplice creare astrazioni in base alle astrazioni in LISP. In Forth, se voglio definire una matrice su uno spazio lineare definito da oggetti con definizioni non banali, passo a Python.

Il motivo è anche evidente, almeno per me. I creatori di LISP sono i matematici, mentre Chuck Moore è l'ultimo esempio di un programmatore pratico, senza mai sprecare il suo tempo in un problema teorico.