2010-04-19 12 views
20

Paul Graham ha scritto che "The unusual thing about Lisp-- in fact, the defining quality of Lisp-- is that it can be written in itself." Ma questo non mi sembra il meno inusuale o definitivo.Cosa significa che "Lisp può essere scritto in sé stesso?"

ISTM che un linguaggio di programmazione è definito da due cose: il suo compilatore o interprete, che definisce la sintassi e la semantica per la lingua da fiat, e la sua libreria standard, che definisce in larga misura gli idiomi e le tecniche che sono esperti gli utenti useranno quando scrivono il codice nella lingua.

Con alcune eccezioni specifiche (ad esempio, i membri non C# della famiglia .NET), le librerie standard della maggior parte delle lingue sono scritte in quella lingua per due buoni motivi: poiché condivideranno lo stesso insieme di definizioni sintattiche, convenzioni di chiamata di funzioni e "aspetto generale" del linguaggio, e perché le persone che sono in grado di scrivere una libreria standard per un linguaggio di programmazione sono i suoi utenti, e in particolare i suoi progettisti. Quindi non c'è niente di unico lì; questo è abbastanza standard.

E ancora, non c'è nulla di unico o inusuale nel compilatore di un linguaggio scritto in sé. I compilatori C sono scritti in C. I compilatori Pascal sono scritti in Pascal. Il compilatore C# di Mono è scritto in C#. Diamine, anche some scripting languages ha implementazioni "scritte in sé".

Quindi cosa significa che Lisp è inusuale per essere scritto in sé stesso?

+6

Come dici tu, un compilatore o un interprete self-hosting non è una grande novità. Un linguaggio il cui albero sintattico astratto * è * il codice, che a sua volta è completamente manipolabile in quanto i dati, al contrario, è piuttosto un animale diverso. Scansionando il documento di McCarthy sul quale stava commentando Paul Graham, non c'è ragione di dubitare che sia questa simmetria a essere nota. –

+2

http://stackoverflow.com/questions/1481053/questo-è-il-exact-definition-of-a-metacircular-interpreter –

risposta

10

Probabilmente ciò che Paolo intende è che la rappresentazione di Lisp sintassi come valore di Lisp è standardizzato e pervasiva. Cioè, un programma Lisp è solo un tipo speciale di S-expression ed è eccezionalmente facile scrivere codice Lisp che manipola il codice Lisp. Scrivere un interprete Lisp in Lisp è un caso speciale, e non è così eccitante come la capacità generale di avere una rappresentazione unificata per codice e dati.

+6

Ciò che descrivi è la proprietà del linguaggio [homoiconic] (http: // en .wikipedia.org/wiki/Homoiconic), che è un tratto condiviso anche da altre lingue. –

+0

@Greg: ho sempre avuto un debole per TRAC (e il suo successore, MINT), ma la mia sensazione è che quei programmatori non hanno mai sfruttato l'omoiconicità nel modo in cui i programmatori Lisp hanno ... –

+3

Non riesco mai a leggere la parola omoiconico senza pensare a Judy Garland. –

7

Bene, il collegamento che hai fornito continua dicendo che, se continui a leggere, risponderà alla tua domanda in dettaglio.

La cosa inusuale Lisp-- in Infatti, la qualità distintiva di Lisp-- è che può essere scritto in sé. Per capire cosa intendesse McCarthy con , ripercorreremo i suoi passi , con la sua notazione matematica tradotta nel codice LIS corrente .

+2

Sì, e poi l'articolo finisce. –

+0

@Mason: è possibile scaricare il file PostScript, convertirlo in PDF qui: http://www.ps2pdf.com/convert.htm e leggerlo utilizzando Adobe Reader. Ha una lunghezza di tredici pagine. –

+1

C'è un collegamento all'articolo completo sulla riga successiva ... – harto

7

Ho appena eliminato una risposta molto lunga che probabilmente è inappropriata qui.

considerare tuttavia che:

  1. LISP non ha "sintassi" se si intende con il significato che ha per linguaggi come C/Java/Pascal ... c'è un (iniziale, ma personalizzabile) sintassi per il lettore Common Lisp, ma questa è una cosa diversa (LISP che Graham sta parlando non è Common Lisp, ed una (la) lettore è non il linguaggio LISP, ma solo una procedura). Qualcosa come "(lambda (x) (* x 2))" è non codice LISP, ma testo che, ad esempio, il lettore standard CL può convertire in codice LISP.

  2. LISP non solo può essere scritto in LISP (se si intende la capacità di "bootstrap") ma in realtà entrato in esistenza in quel modo. La primissima implementazione di eval alla fine degli anni '50 è stata scritta in LISP su carta e poi convertita manualmente nella lingua della macchina (1): LISP è iniziato come un'idea puramente teorica non pensata per essere implementata. Non conosco altri linguaggi del computer che seguissero il percorso . Ad esempio C++ è stato concepito come pre-processore per un compilatore C ed è stato scritto in C, non era un programma C++ successivamente convertito in C per essere in grado di eseguirlo.

Ci sono molti altri aspetti in cui LISP è abbastanza diversa, e penso che il modo migliore per ottenere una comprensione di esso è quello di implementare in realtà un interprete giocattolo LISP (è un lavoro più piccolo di quanto si potrebbe pensa in particolare se il tuo "linguaggio macchina" è un linguaggio di alto livello scritto in modo dinamico come Python).

(1) in http://www-formal.stanford.edu/jmc/history/lisp/node3.html si possono trovare come McCarthy descrive la eval[e, a] è stato trovato su carta in primo luogo come un risultato teorico interessante (una "funzione universale" più ordinato implementazione di una macchina universale di Turing) quando solo le strutture dati e le funzioni native elementari era stato progettato per la lingua Lisp che il gruppo stava costruendo. Questa funzione scritta a mano è stata implementata a mano da S.R. Russell in codice macchina e ha iniziato a servirli come primo interprete Lisp.

+0

Dove posso trovare che "la prima implementazione di eval alla fine degli anni '50 [che è stata scritta in LISP su carta" –

+0

@ RenéG: Vedi la risposta modificata, ho aggiunto un riferimento. – 6502

6

Non sta dicendo che Lisp può essere utilizzato per scrivere un compilatore Lisp. Sta dicendo che il linguaggio è costituito dalle sue strutture dati. Quindi, mentre non è possibile creare una funzione C da strutture dati C, è possibile farlo in Lisp. Un programma è composto da liste che vengono eseguite dal computer e l'effetto di tali elenchi può essere quello di creare altri elenchi che vengono quindi eseguiti e l'effetto di tali elenchi può essere quello di creare ancora più elenchi da eseguire. C non ha questa proprietà. Il codice C non può, per esempio, manipolare il proprio AST.

+1

Il codice C può essere modificato da solo. In realtà, credo che il Codice di auto-modifica sia stato abbastanza popolare per un po '. – Ponkadoodle

+5

@wallacoloo: C'è una sottile distinzione tra * lingua * e * implementazione * qui. Il codice C non può manipolare ** stesso **, ma può manipolare il ** codice macchina ** codice in cui è implementato. Questo è un livello completamente diverso di astrazione dalla manipolazione del codice Lisp in Lisp. –

+0

Oh, la parola chiave era AST, che è o una modifica, o qualcosa che ho perso. Scusa, e grazie per il chiarimento. – Ponkadoodle

4

L'idea principale è che il linguaggio Lisp ha un kernel molto piccolo di una manciata di funzioni e il meccanismo di valutazione principale può essere scritto in codice su una singola pagina.

Questo è il core di Lisp.

a capire il funzionamento di base del linguaggio è necessario solo per guardare quella sola pagina di codice: spiega come funzionano le variabili, come la funzione di chiamata funziona, come le nuove funzioni possono essere creati, ecc

Proprio pensa a quanto puoi rimuovere da un'implementazione linguistica per ottenere le basi. Qual è il set minimo di primitive e qual è il motore di esecuzione minimo. Per scrivere un Lisp in un Lisp, non scendere quasi nulla.

Se si considera un'implementazione PASCAL (ad esempio), non è implementato in PASCAL, ma in PASCAL + una quantità maggiore di codice che fornisce le strutture dati necessarie per rappresentare entità linguaggio, un parser, un compilatore, un runtime, ... - out of the box PASCAL non offre molto - bisogna costruirli (o usare una libreria).

Wirth (il creatore di Pascal) ha scritto un libro che spiega l'implementazione di un linguaggio Pascal molto piccolo - devi ancora scrivere codice sostanziale per implementare quella lingua: parser, generatore di codice, runtime, loader,. ..

Al contrario, in un Lisp, il codice sorgente Lisp ha una rappresentazione naturale e la routine di base che valuta il codice Lisp è solo una funzione Lisp. Ciò potrebbe non essere un'implementazione Lisp reale o pratica, tuttavia è diversa dalla situazione PASCAL, in cui il codice sorgente non ha alcuna rappresentazione utile (diversa da una stringa o un file) e il motore di esecuzione è molto più codice.

Quindi, in Lisp abbiamo:

  • una rappresentazione semplice per il codice sorgente (liste di simboli)

  • una semplice implementazione del valutatore in una sola piccola funzione

Oltre a ciò, non è necessario nulla per implementare un valutatore Lisp in Lisp.

Problemi correlati