Domanda

Ho letto molto che LISP può ridefinire la sintassi al volo, presumibilmente con le macro.Sono curioso di sapere fino a che punto arriva effettivamente questo?Riesci a ridefinire la struttura del linguaggio in modo che diventi borderline un compilatore per un'altra lingua?Ad esempio, potresti cambiare la natura funzionale di LISP in una sintassi e una semantica più orientate agli oggetti, magari dicendo di avere una sintassi più vicina a qualcosa come Ruby?

Soprattutto, è possibile liberarsi dell'inferno delle parentesi utilizzando le macro?Ho imparato abbastanza (Emacs-)LISP per personalizzare Emacs con le mie micro-funzionalità, ma sono molto curioso di sapere fino a che punto le macro possano spingersi nella personalizzazione del linguaggio.

È stato utile?

Soluzione

Questa è davvero una bella domanda.

Penso che sia sfumato ma sicuramente rispondente:

Le macro non sono bloccate nelle espressioni s.Vedi la macro LOOP per un linguaggio molto complesso scritto utilizzando parole chiave (simboli).Quindi, anche se puoi iniziare e terminare il ciclo con parentesi, al suo interno ha una propria sintassi.

Esempio:

(loop for x from 0 below 100
      when (even x)
      collect x)

Detto questo, la maggior parte delle macro semplici utilizza solo le espressioni s.E rimarresti "bloccato" a usarli.

Ma le espressioni S, come ha risposto Sergio, iniziano a sembrare giuste.La sintassi viene tolta di mezzo e si inizia a scrivere codice nell'albero della sintassi.

Per quanto riguarda le macro dei lettori, sì, potresti plausibilmente scrivere qualcosa del genere:

#R{
      ruby.code.goes.here
  }

Ma dovresti scrivere il tuo parser della sintassi Ruby.

Puoi anche imitare alcuni dei costrutti Ruby, come i blocchi, con macro che si compilano sui costrutti Lisp esistenti.

#B(some lisp (code goes here))

si tradurrebbe in

(lambda () (some lisp (code goes here)))

Vedere questa pagina per sapere come farlo.

Altri suggerimenti

Sì, puoi ridefinire la sintassi in modo che Lisp diventi un compilatore.Puoi farlo utilizzando le "Macro del lettore", che sono diverse dalle normali "Macro del compilatore" a cui probabilmente stai pensando.

Common Lisp ha la funzionalità incorporata per definire una nuova sintassi per il lettore e le macro del lettore per elaborare quella sintassi.Questa elaborazione viene eseguita in fase di lettura (che viene prima del momento della compilazione o della valutazione).Per saperne di più sulla definizione delle macro dei lettori in Common Lisp, consulta Common Lisp Hyperspec: ti consigliamo di leggere cap.2, "Sintassi" E cap.23, "Lettore".(Credo che Scheme abbia la stessa funzionalità, ma non ne ho molta familiarità - vedi Fonti dello schema per il Linguaggio di programmazione ad arco).

Come semplice esempio, supponiamo che tu voglia che Lisp utilizzi le parentesi graffe anziché le parentesi.Ciò richiede qualcosa come le seguenti definizioni di lettore:

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

Stai dicendo a Lisp che { è come a ( e che } è come a ).Quindi crei una funzione (lcurly-brace-reader) che il lettore chiamerà ogni volta che vede un { e tu usi set-macro-character per assegnare quella funzione al {.Quindi dici a Lisp che ( e ) sono come [ e ] (ovvero, sintassi non significativa).

Altre cose che potresti fare includono, ad esempio, creando una nuova sintassi della stringa oppure utilizzando [ e ] per racchiudere la notazione fissa ed elaborarla in espressioni S.

Puoi anche andare ben oltre, ridefinendo l'intera sintassi con i tuoi macro caratteri che scateneranno azioni nel lettore, quindi il cielo è davvero il limite.Questo è solo uno dei motivi per cui Paolo Graham E altri continuo a dire che Lisp è un buon linguaggio in cui scrivere un compilatore.

Non sono un esperto di Lisp, diamine, non sono nemmeno un programmatore di Lisp, ma dopo un po' di esperimenti con il linguaggio sono giunto alla conclusione che dopo un po' le parentesi iniziano a diventare 'invisibili' e inizi a vedere il codice come vuoi che sia.Inizi a prestare maggiore attenzione ai costrutti sintattici che crei tramite s-exprs e macro e meno alla forma lessicale del testo di elenchi e parentesi.

Ciò è particolarmente vero se ti avvali di un buon editor che ti aiuta con il rientro e la colorazione della sintassi (prova a impostare la parentesi su un colore molto simile allo sfondo).

Potresti non essere in grado di sostituire completamente la lingua e ottenere la sintassi "Ruby", ma non ne hai bisogno.Grazie alla flessibilità del linguaggio potresti finire con un dialetto che ti fa sentire come se stessi seguendo lo "stile di programmazione Ruby", se lo desideri, qualunque cosa significhi per te.

So che questa è solo un'osservazione empirica, ma penso di aver avuto uno di quei momenti di illuminazione Lisp in cui me ne sono reso conto.

Più e più volte, i nuovi arrivati ​​a Lisp vogliono "sbarazzarsi di tutte le parentesi". Dura alcune settimane.Nessun progetto per costruire una seria sintassi di programmazione per scopi generici in cima al solito parser di espressione S mai arriva ovunque, perché i programmatori invariabilmente finiscono preferendo ciò che attualmente percepisci come "tra parentesi". Ci vuole un po 'di tempo per abituarsi, ma non molto!Una volta che ti sei abituato e puoi davvero apprezzare la plasticità della sintassi predefinita, tornare a linguaggi in cui esiste un solo modo per esprimere un particolare costrutto di programmazione è davvero irritante.

Detto questo, Lisp è un eccellente substrato per la creazione di linguaggi specifici del dominio.Buono quanto, se non migliore, di XML.

Buona fortuna!

La migliore spiegazione delle macro Lisp che abbia mai visto è in

https://www.youtube.com/watch?v=4NO83wZVT0A

a partire da circa 55 minuti.Questo è il video di un discorso tenuto da Peter Seibel, l'autore di "Practical Common Lisp", che è il miglior libro di testo Lisp che esista.

La motivazione per le macro Lisp è solitamente difficile da spiegare, perché entrano davvero in gioco in situazioni che sono troppo lunghe per essere presentate in un semplice tutorial.Peter fornisce un ottimo esempio;puoi coglierlo completamente e fa un uso corretto e corretto delle macro Lisp.

Hai chiesto:"potresti cambiare la natura funzionale di LISP in una sintassi e una semantica più orientate agli oggetti".La risposta è si.In effetti, Lisp originariamente non aveva alcuna programmazione orientata agli oggetti, il che non sorprende dal momento che Lisp esiste da molto prima della programmazione orientata agli oggetti!Ma quando abbiamo appreso per la prima volta dell'OOP nel 1978, siamo stati in grado di aggiungerlo facilmente al Lisp, utilizzando, tra le altre cose, le macro.Alla fine fu sviluppato il Common Lisp Object System (CLOS), un sistema di programmazione orientato agli oggetti molto potente che si adatta elegantemente al Lisp.Il tutto può essere caricato come estensione: non c'è nulla di integrato!È tutto fatto con le macro.

Lisp ha una caratteristica completamente diversa, chiamata "macro del lettore", che può essere utilizzata per estendere la sintassi superficiale del linguaggio.Usando le macro del lettore, puoi creare sottolinguaggi con sintassi simile a C o Ruby.Trasformano il testo in Lisp, internamente.Questi non sono ampiamente utilizzati dalla maggior parte dei veri programmatori Lisp, principalmente perché è difficile estendere l'ambiente di sviluppo interattivo per comprendere la nuova sintassi.Ad esempio, i comandi di indentazione di Emacs verrebbero confusi da una nuova sintassi.Se sei energico, però, anche Emacs è estensibile e potresti insegnargli la tua nuova sintassi lessicale.

Le macro regolari operano su elenchi di oggetti.Più comunemente, questi oggetti sono altri elenchi (che formano quindi alberi) e simboli, ma possono essere altri oggetti come stringhe, tabelle hash, oggetti definiti dall'utente, ecc.Queste strutture sono chiamate s-esp.

Pertanto, quando carichi un file sorgente, il tuo compilatore Lisp analizzerà il testo e produrrà s-exp.Le macro operano su questi.Funziona alla grande ed è un modo meraviglioso per estendere la lingua nello spirito delle s-exp.

Inoltre, il suddetto processo di analisi può essere esteso tramite "macro di lettura" che ti consentono di personalizzare il modo in cui il compilatore trasforma il testo in s-exp.Suggerisco, tuttavia, di abbracciare la sintassi del Lisp invece di piegarla a qualcos'altro.

Sembri un po' confuso quando menzioni la "natura funzionale" di Lisp e la "sintassi orientata agli oggetti" di Ruby.Non sono sicuro di cosa dovrebbe essere la "sintassi orientata agli oggetti", ma Lisp è un linguaggio multi-paradigma e supporta la programmazione orientata agli oggetti estremamente BENE.

A proposito, quando dico Lisp, intendo Lisp comune.

Ti suggerisco di mettere da parte i tuoi pregiudizi e dai a Lisp un tentativo onesto.

Parentesi infernale?Non vedo più parentesi in:

(function toto)

che in:

function(toto);

E dentro

(if tata (toto)
  (titi)
  (tutu))

non più che in:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

Vedo meno parentesi e ';' Anche se.

Quello che stai chiedendo è un po' come chiedere come diventare un esperto cioccolatiere in modo da poter rimuovere tutta quella roba marrone infernale dalla tua torta al cioccolato preferita.

Sì, puoi cambiare radicalmente la sintassi e persino sfuggire "all'inferno delle parentesi".Per questo dovrai definire una nuova sintassi del lettore.Esamina le macro del lettore.

Sospetto tuttavia che per raggiungere il livello di competenza Lisp necessario per programmare tali macro dovrai immergerti nella lingua a tal punto da non considerare più le parentesi "un inferno".Cioè.quando saprai come evitarli, sarai arrivato ad accettarli come una buona cosa.

Se vuoi che il lisp assomigli a Ruby usa Ruby.

È possibile usare Ruby (e Python) in modo molto fluido, il che è uno dei motivi principali per cui hanno ottenuto l'accettazione così rapidamente.

guarda questo esempio di come le macro del lettore possono estendere il lettore lisp con attività complesse come i modelli XML:

http://common-lisp.net/project/cl-quasi-quote/present-class.html

Questo libreria utente compila le parti statiche dell'XML in array di byte letterali codificati UTF-8 in fase di compilazione, pronti per essere sequenziati in scrittura nel flusso di rete.e sono utilizzabili nelle normali macro lisp, sono ortogonali...il posizionamento del carattere virgola influenza quali parti sono costanti e quali dovrebbero essere valutate in fase di esecuzione.

maggiori dettagli disponibili su: http://common-lisp.net/project/cl-quasi-quote/

un altro progetto che per le estensioni della sintassi Common Lisp: http://common-lisp.net/project/cl-syntax-sugar/

@sparkes

A volte LISP è la scelta linguistica più chiara, vale a dire le estensioni Emacs.Sono sicuro che potrei usare Ruby per estendere Emacs se lo volessi, ma Emacs è stato progettato per essere esteso con LISP, quindi sembra avere senso usarlo in quella situazione.

È una domanda complicata.Poiché lisp è già strutturalmente così vicino ad un albero di analisi, la differenza tra un gran numero di macro e l'implementazione del proprio mini-linguaggio in un generatore di parser non è molto chiara.Ma, fatta eccezione per le parentesi di apertura e chiusura, potresti facilmente ritrovarti con qualcosa che non assomiglia per niente al lisp.

Uno degli usi delle macro che mi ha lasciato senza parole è stata la verifica in fase di compilazione delle richieste SQL rispetto al DB.

Una volta che ti rendi conto di avere il linguaggio completo a portata di mano in fase di compilazione, si aprono nuove interessanti prospettive.Ciò significa anche che puoi darti la zappa sui piedi in nuovi modi interessanti (come la compilazione di rendering non riproducibili, che può facilmente trasformarsi in un incubo di debug).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top