Perché studiare un interprete lisp in lisp è così importante?


30

Ho visto molti curriculum CS e suggerimenti di apprendimento per i nuovi programmatori che chiedono all'aspirante programmatore di studiare un interprete lisp che è specificamente scritto in lisp. Tutti questi siti dicono cose simili a "è una rivelazione intellettuale", "è un'esperienza illuminante che ogni programmatore serio dovrebbe avere", o "ti mostra relazioni hardware / software" e altre dichiarazioni vaghe, in particolare da questo articolo tratto da questo stimabile how-to .

Il sentimento generale della mia domanda è: come fa lisp a raggiungere i suddetti obiettivi e perché lisp? Perché non un'altra lingua?

Lo sto chiedendo perché ho appena finito di scrivere un interprete di schemi in schema (tratto da SICP http://mitpress.mit.edu/sicp/ ) e ora sto scrivendo un interprete di pitone in schema e sto lottando per avere questa leggendaria epifania ciò dovrebbe provenire specificamente dal primo. Sto cercando dettagli tecnici specifici tra le due lingue che posso sfruttare nei loro interpreti di schemi per capire come funzionano i programmi.

Più specificamente:

Perché lo studio di un interprete scritto nella lingua che interpreta è così enfatizzato? È semplicemente un grande esercizio mentale mantenere la lingua originale e la lingua costruita o ci sono problemi specifici le cui soluzioni possono essere trovate solo nella natura del lingua originale?

In che modo gli interpreti lisp dimostrano buoni concetti di architettura per il futuro design del software?

Cosa mi perderei se facessi questo esercizio in un linguaggio diverso come C ++ o Java?

Qual è lo strumento da asporto o lo "strumento mentale" più utilizzato da questo esercizio? **

** Ho selezionato la risposta l'ho fatto perché mi sono accorto che ho guadagnato da questo esercizio più abilità nella progettazione di strumenti di parsing nella mia testa rispetto a qualsiasi altro strumento unico e mi piacerebbe trovare diversi metodi di analisi che possono lavorare meglio per il regime interprete dell'interprete python.



4
@gnat Non è esattamente un consiglio di carriera, più una domanda "cosa c'è di così bello in Lisp".
Robert Harvey,

1
@RobertHarvey quel link non è solo per la carriera ma anche per i consigli educativi , intendevo questo. Ma, beh, anche Lisp-is-so-great è una buona scelta
moscerino del

1
Sembra che ti stia chiedendo cosa imparerai da un esercizio particolare. La tua reticenza è un segno di pigrizia, chiave per ogni buon programmatore, ma indipendentemente dall'unico modo per scoprire cosa imparerai da un esercizio è farlo e vedere. Nessuno può dirti cosa imparerai da farlo, dovrai solo farlo.
Jimmy Hoffa,

2
Sebbene questa domanda riguardi l'istruzione nel suo insieme, non la classificherei come "consiglio di istruzione" nel modo "Quale lingua dovrei imparare?" è. Cioè, non è specifico per un certo tipo di corso o lavoro. In effetti, se si eliminano alcune delle parole d'ordine dell'educazione, questa è una domanda sulla programmazione dei linguaggi nel loro insieme, le cui risposte discutono le caratteristiche del linguaggio. Non è nemmeno specifico per Lisp, ma può essere applicato ad altri linguaggi omoiconici come xslt. Quindi non dirò che questa è una domanda perfetta, solo che non è semplicemente un "consiglio di carriera".
TheRubberDuck,

Risposte:


17

A rischio di dare una risposta "anch'io", se lo provi vedrai ...

Se studi i linguaggi del computer, è probabile che tu abbia l'impressione che almeno la metà riguardi l'analisi. Se impari Lisp, ti renderai conto che l'analisi della sintassi di superficie non è altro che una comodità per le persone (come la maggior parte di noi) a cui non piacciono molte parentesi singole irritanti.

Quindi potresti capire che un grande prezzo è stato pagato per quella comodità. In Lisp è banale per un programma creare un altro programma ed eseguirlo. In altre lingue è una tecnica avanzata, come fare moltiplicazioni in numeri romani.

Certo, quasi tutti chiedono "chi deve farlo?" Bene, potresti benissimo vedere che si apre un'intera vista di cose che non hai nemmeno realizzato di non poter fare prima. Puoi farlo in altre lingue, ma non così facilmente.

INSERITO per rispondere al commento di Izkata:

  • Il programma di comprensione del linguaggio naturale SHRDLU ha funzionato traducendo una dichiarazione o una domanda inglese in un programma in un dialetto Lisp chiamato MICRO-PLANNER ed eseguendolo.
  • I programmi che manipolano i programmi, ad esempio per semplificarli o dimostrarli corretti, sono naturalmente scritti in Lisp.
  • Ho usato la generazione di programmi in un programma per comprendere scene visive, in cui doveva affrontare tutte le simmetrie capaci di oggetti tridimensionali, senza moltiplicare il codice.
  • Qualsiasi cosa abbia a che fare con la logica e la dimostrazione di teoremi si occupa della manipolazione delle espressioni logiche, che sono una forma di programma.
  • La matematica simbolica, come il calcolo simbolico integrale o differenziale, comporta la manipolazione delle espressioni matematiche, che sono come programmi in miniatura.
  • Qualsiasi problema che coinvolga la generazione di codice, o il termine più alto "valutazione parziale", è naturale in Lisp. L'ho fatto per un programma bridge database molto tempo fa. L'ho fatto in C, che non è stato facile come Lisp, ma ho avuto l'idea da Lisp. Quella era considerata una tecnica che quasi nessuno poteva fare in quel momento (specialmente le teste COBOL). Forse di più ora, spero.

... sono solo alcuni ...

Poi ti rendi conto che alcune cose che oggi sono considerate "moderne" sono state fatte a Lisp da 40 anni. Come la programmazione funzionale. Come la raccolta dei rifiuti. Come chiusure.

Questo non vuol dire che le lingue moderne non abbiano nuove buone idee, come OOP, ecc. Ma se impari Lisp allargherà la tua prospettiva.


You can do it in other languages, but not nearly so easily.- Piace? (La domanda per me sembra essere perché dichiarazioni come queste sono spesso fatte, ma quasi mai diventano più specifiche)
Izkata

Ho pensato per la prima volta che il mondo fosse stato rivoluzionato quando mi sono reso conto che javascript poteva stampare il proprio codice sorgente e che gli oggetti potevano essere attraversati per ottenere stringhe letterali che possono essere evocate nell'oggetto letterale. Poi ho capito che Perl aveva tutto questo insieme a $ Data :: Dumper :: Deparse, e poi ho capito che lisp aveva questo per sempre. Comprendere gli interpreti sblocca questo potere che ha sempre lì per costruire moduli viventi, e in Lisp questo è più accessibile di qualsiasi altra lingua.
Dmitry

la cosa divertente è che un programmatore di Lisp consapevole degli interni di Lisps può sempre creare il proprio frontend Lisp per qualsiasi linguaggio dinamico da javascript a bash o perl o python; lisp piacevolmente bootstrap dall'ambiente disponibile.
Dmitry

19

La semplice risposta alla tua domanda è provare Lisp, preferibilmente in combinazione con SICP . Allora sarai illuminato.

Detto ciò...

Il codice è dati
La maggior parte delle lingue fa una netta distinzione tra codice e dati; Lisp no. Ciò consente, ad esempio, di scrivere banalmente un parser Lisp in Lisp e di manipolare il codice Lisp in Lisp. La migliore descrizione di questa illuminazione che ho trovato è The Nature of Lisp .

Questo è vero in parte perché la sintassi per la lingua è così semplice. Rende possibili cose in Lisp (come la metaprogrammazione) che sono poco pratiche in altre lingue perché la sintassi si mette in mezzo.

Ulteriori letture
battendo le medie


3
Il secondo paragrafo non ha senso: omoiconicità! = Sintassi semplice; la sintassi semplice semplifica la scrittura di un parser Lisp in qualsiasi lingua (vedi questo ). Il 3 ° paragrafo è vago, necessita di esempi.

@MattFenwick è vero che l'omoiconicità può essere fatta con una sintassi complessa, ma sarebbe estremamente difficile. È giusto supporre che se si ha a che fare con una sintassi omoiconica, sarà semplice, se non altro per la coerenza richiesta da essa che renderà ineffabilmente più facile da seguire di una sintassi non omoiconica. Sebbene il tuo secondo punto sia positivo, LISP è facile da analizzare perché è una sintassi semplice, non a causa dell'omoiconicità (anche se l'omoiconicità è la causa di quella semplicità)
Jimmy Hoffa

1
In ogni caso, c'è un piccolo sovraccarico nel prendere un valore di dati e interpretarlo come programma. Questa è una bella cosa La programmazione per configurazione è semplice quando tutto ciò che devi fare è scrivere un interprete per i dati di configurazione. Trasformazioni matematiche avanzate (che sono difficili da implementare in lingue stateful) sono spesso "ridotte" a semplici trasformazioni sintattiche del puro frammento di Lisp.
nomen

1
@MattFenwick: ho rimosso la parola "omoiconicità" dalla mia risposta.
Robert Harvey,

1
Vorrei poter dare più di un +1 per The Nature of Lisp; Non ho mai visto una spiegazione così grande.
Doval,

9

Perché lo studio di un interprete scritto nella lingua che interpreta è così enfatizzato?

In generale, studiare un interprete ti dà un'idea della sua lingua e delle sue caratteristiche. In generale, studiare il codice in un linguaggio di programmazione è come praticare una lingua parlata ascoltando e leggendo: ti familiarizza con ciò che quella lingua può fare, come viene usata e "idiomi" comuni. Più specificamente, Lisp è un linguaggio omoiconico, il che significa che la sua sintassi per le espressioni è la stessa della sua sintassi per i dati. Scrivere codice in Lisp sembra terribilmente come se stessi scrivendo un elenco e viceversa. Pertanto, interpretare il codice Lisp con il codice Lisp è semplice come scorrere le liste con care cdr.

Come dovrei capitalizzare su questo esercizio per trarne il massimo concettualmente?

Pensa a come l'interprete si interpreterebbe da solo - in molte implementazioni di interpreti meta-circolari (dove un linguaggio omoiconico interpreta se stesso) può semplicemente "passare" attraverso la funzione. Ad esempio, per implementare car, basta prendere carl'argomento. Ciò toglie l'enfasi ai meccanismi di archiviazione dei dati e si concentra sulla funzionalità.

In che modo gli interpreti lisp dimostrano buoni concetti di architettura per il futuro design del software?

Gli interpreti possono essere molto complicati, il che incoraggia una buona architettura nel progettarli. Con questo in mente, questo dipende maggiormente dall'interprete individuale.

Cosa mi perderei se facessi questo esercizio in un linguaggio diverso come C ++ o Java?

Queste lingue non sono omoiconiche, quindi non beneficiano della grazia e della semplicità di un interprete Lisp meta-circolare. Questo rende l'esercizio più difficile e forse meno comune, ma non direi che è davvero meno benefico.

Qual è lo strumento da asporto o lo "strumento mentale" più utilizzato da questo esercizio?

Non sono sicuro di avere una buona risposta per questo; semplicemente che aiuta a vedere come funziona l'interprete e, forse ancora più importante, armeggiare con esso per vedere come possono essere facilmente implementate piccole modifiche alla lingua.


5

LISP è esso stesso strutturato in un modo che lo rende estremamente facile da analizzare. Se provi a scrivere un compilatore, noterai che è molto più semplice se tutto nella tua lingua è un'espressione e ha un basso livello di ambiguità. LISP forza le parentesi ovunque per eliminare l'ambiguità e non ha dichiarazioni, solo espressioni.

Il fatto stesso che LISP sia molto facile da analizzare incoraggia gli utenti ad analizzare il proprio codice sorgente e fare trucchi magici con esso. La linea tra dati e codice diventa sfocata e puoi facilmente fare cose che normalmente richiedono un certo sforzo, come la riflessione, la riscrittura dinamica del codice, i plugin e la serializzazione.

Questo è il senso. L'esercizio probabilmente ha lo scopo di darti un'idea di ciò che è possibile quando il codice è facilmente analizzabile da se stesso.


Non è facile da analizzare Lisp. Le espressioni S sono facili da analizzare. Inoltre, devi analizzare Lisp.
Rainer Joswig,

@Rainer: Non è solo un pignolo? Nel mio mondo analizzare significa passare dal testo a un AST, che non dice nulla sull'interpretazione dei comandi.
Alexander Torstling,

In C ++ il parser rileverà una dichiarazione di funzione sintatticamente errata. A Lisp no. Il lettore non sa nulla del linguaggio di programmazione Lisp. Il parser C ++ conosce la sintassi completa C ++. Il lettore Lisp conosce solo espressioni S.
Rainer Joswig

Ah, allora capisco cosa intendi. È vero, anche se penso ancora che un semplice valutatore lisp sarebbe più semplice da costruire rispetto a un semplice c ++. È quello che fanno in SICP, no (è da un po 'che non lo leggo)?
Alexander Torstling

il linguaggio usato in SICP è molto semplice, nemmeno Schema completo. Un interprete per un linguaggio minuscolo in C dovrebbe anche essere semplice. C ++ è grande. Alcune delle sue difficoltà derivano da un numero relativamente elevato di sintassi integrata. In un tipico sistema Lisp gran parte della sintassi è costruita con macro - al di fuori dell'interprete. Le macro implementano la sintassi e un meccanismo di estensione per le trasformazioni di origine. Questo mantiene il nucleo più piccolo. Ma le macro possono essere enormi. Ad esempio l'implementazione per il costrutto LOOP ha più di 2000 righe di codice macro complesso.
Rainer Joswig

4

Non sono sicuro che sia davvero importante per tutti. Puoi essere uno sviluppatore di successo senza sapere come funziona un interprete Lisp. Quando si studia Informatica, le idee di base di Lisp dovrebbero comunque essere apprese.

Gli interpreti Lisp sono importanti per i programmatori Lisp. Devono capire come funziona un interprete ([e compilatore] 1 ), per comprendere appieno come usare la lingua.

Un interprete Lisp viene spesso utilizzato come strumento di informatica per insegnare agli studenti alcune cose:

Come dispositivo didattico, un interprete Lisp è utile, perché può essere appreso e compreso in breve tempo. Dato che pochi studenti conoscono già Lisp, gli studenti sono su un piano di livello quando si tratta di apprendere al di sopra dei concetti.

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.