Schema vs Common Lisp: quali caratteristiche hanno fatto la differenza nel tuo progetto? [chiuso]


155

Non mancano vaghe domande "Scheme vs Common Lisp" sia su StackOverflow che su questo sito, quindi voglio renderlo più focalizzato. La domanda è per le persone che hanno codificato in entrambe le lingue:

Durante la programmazione in Scheme, quali elementi specifici della tua esperienza di programmazione in Common Lisp ti sei perso di più? O, al contrario, durante la codifica in Common Lisp, cosa ti sei perso a scrivere in Scheme?

Non intendo necessariamente solo funzionalità linguistiche. Per quanto riguarda la domanda, ci sono tutte le cose valide da perdere:

  • Biblioteche specifiche.
  • Funzionalità specifiche di ambienti di sviluppo come SLIME, DrRacket, ecc.
  • Funzionalità di implementazioni particolari, come la capacità di Gambit di scrivere blocchi di codice C direttamente nel tuo sorgente Scheme.
  • E, naturalmente, funzionalità linguistiche.

Esempi del tipo di risposte che spero:

  • "Stavo cercando di implementare X in Common Lisp, e se avessi avuto le continuazioni di prima classe di Scheme, avrei semplicemente fatto Y, ma invece avrei dovuto fare Z, il che era più un dolore."
  • "Lo scripting del processo di compilazione nel mio progetto Scheme è diventato sempre più doloroso man mano che il mio albero dei sorgenti cresceva e mi collegavo a sempre più librerie C. Per il mio prossimo progetto, sono tornato al Common Lisp."
  • "Ho una grande base di codici C ++ esistente e, per me, essere in grado di incorporare le chiamate C ++ direttamente nel mio codice del Gambit Scheme è valsa la pena qualsiasi carenza che Scheme potrebbe avere rispetto al Common Lisp, inclusa la mancanza di supporto SWIG."

Quindi, spero in storie di guerra, piuttosto che in sentimenti generali come "Lo schema è un linguaggio più semplice" ecc.


25
Un'ottima domanda ben formulata. Sono curioso di questo io stesso; si spera che ci siano alcune persone là fuori con esperienza in entrambe le lingue disposte a fornire alcune informazioni.
Robert Harvey,

1
@Josh K - è chiaramente rispondibile, ma non esiste necessariamente un'unica risposta definitiva. Tranne che scommetto che ce ne sarà uno perché qualcuno uscirà con una risposta così fantastica che tutti sono come whoa!
glenatron,

4
@Josh: Allora forse non hai familiarità con Scheme e Common Lisp. Entrambe le lingue sono molto potenti di per sé, ma non hanno nemmeno un'accettazione generale. Perchè è questo? Potrebbe essere perché ci sono così tanti dialetti; Quale scegli? Un confronto di questo tipo potrebbe essere molto illuminante e l'OP ha formulato attentamente la domanda per limitare l'ambito di applicazione a risposte che, a mio avviso, sono molto specifiche e rispondenti.
Robert Harvey,

13
Gente, non chiudere la domanda solo perché non ti piace o non riesci a metterti in relazione. È chiaramente una domanda "reale"; se non riesci a trovare un motivo migliore per chiuderlo, non dovresti votare per chiudere.
Robert Harvey,

4
Puoi inviare una email a Richard Stallman per la sua risposta.
Wassimans,

Risposte:


100

La mia laurea era in Scienze cognitive e intelligenza artificiale. Da quel momento ho avuto un'introduzione di un corso a Lisp. Ho pensato che la lingua fosse interessante (come in "elegante") ma non ci ho pensato molto fino a quando non ho incontrato la Decima Regola di Greenspun molto più tardi:

Qualsiasi programma C o Fortran sufficientemente complicato contiene un'implementazione lenta ad hoc, specificata in modo informatico, inficiata da bug, di metà di Common Lisp.

Il punto di Greenspun era (in parte) che molti programmi complessi hanno interpreti incorporati. Invece di costruire un interprete in una lingua, ha suggerito che potrebbe avere più senso usare una lingua come Lisp che ha già un interprete (o un compilatore) incorporato.

All'epoca lavoravo su un'app piuttosto grande che eseguiva calcoli definiti dall'utente usando un interprete personalizzato per un linguaggio personalizzato. Ho deciso di provare a riscrivere il suo core in Lisp come esperimento su larga scala.

Ci sono volute circa sei settimane. Il codice originale era ~ 100.000 righe di Delphi (una variante Pascal). In Lisp che è stato ridotto a ~ 10.000 linee. Ancora più sorprendente, tuttavia, è stato il fatto che il motore Lisp era 3-6 volte più veloce. E tieni presente che questo era il lavoro di un neofita di Lisp! Tutta questa esperienza mi ha aperto gli occhi; per la prima volta ho visto la possibilità di combinare prestazioni ed espressività in una sola lingua.

Qualche tempo dopo, quando ho iniziato a lavorare su un progetto basato sul web, ho fatto il provino in diverse lingue. Ho incluso Lisp e Scheme nel mix. Alla fine ho selezionato un'implementazione dello Schema - Chez Scheme . Sono stato molto contento dei risultati.

Il progetto basato sul web è un "motore di selezione" ad alte prestazioni . Utilizziamo Scheme in diversi modi, dall'elaborazione dei dati alla query dei dati alla generazione della pagina. In molti punti abbiamo effettivamente iniziato con una lingua diversa, ma abbiamo finito con la migrazione allo Schema per i motivi che descriverò brevemente di seguito.

Ora posso rispondere alla tua domanda (almeno in parte).

Durante l'audizione abbiamo esaminato una varietà di implementazioni di Lisp e Scheme. Sul lato Lisp abbiamo esaminato (credo) Allegro CL, CMUCL, SBCL e LispWorks. Per quanto riguarda lo Scheme abbiamo esaminato (credo) Bigloo, Chicken, Chez, Gambit. (La selezione della lingua è stata molto tempo fa; ecco perché sono un po 'confuso. Posso prendere appunti se è importante.)

Stavamo cercando a) thread nativi eb) supporto Linux, Mac e Windows. Queste due condizioni combinate hanno messo tutti al tappeto ma (penso) Allegro e Chez - quindi per continuare la valutazione abbiamo dovuto allentare il requisito del multi-threading.

Abbiamo messo insieme una serie di piccoli programmi e li abbiamo usati per valutazione e test. Ciò ha rivelato una serie di problemi. Ad esempio: alcune implementazioni presentavano difetti che impedivano l'esecuzione di alcuni test fino al completamento; alcune implementazioni non sono riuscite a compilare il codice in fase di esecuzione; alcune implementazioni non potevano facilmente integrare il codice compilato di runtime con il codice precompilato; alcune implementazioni avevano dei bidoni della spazzatura che erano chiaramente migliori (o chiaramente peggiori) di altri; eccetera.

Per le nostre esigenze solo le tre implementazioni commerciali - Allegro, Chez e Lispworks - hanno superato i nostri test primari. Dei tre solo Chez ha superato tutti i test a pieni voti. All'epoca penso che Lispworks non avesse thread nativi su nessuna piattaforma (penso che lo facciano ora) e penso che Allegro avesse solo thread nativi su alcune piattaforme. Inoltre, Allegro aveva una tassa di licenza di runtime "chiamaci" che non mi piaceva molto. Credo che Lispworks non avesse alcun costo di runtime e Chez avesse un accordo semplice (e molto ragionevole) (e si è avviato solo se hai usato il compilatore in fase di runtime).

Avendo prodotto blocchi di codice piuttosto significativi sia in Lisp sia in Scheme, ecco alcuni punti di confronto e contrasto:

  • Gli ambienti Lisp sono molto più maturi. Ottieni molto di più per il dollaro. (Detto questo, più codice equivale anche a più bug.)

  • Gli ambienti Lisp sono molto più difficili da imparare. Hai bisogno di molto più tempo per diventare esperto; Common Lisp è un linguaggio enorme - ed è prima di arrivare alle librerie che le implementazioni commerciali aggiungono sopra di esso. (Detto questo, il caso della sintassi di Scheme è molto più sottile e complicato di qualsiasi cosa in Lisp.)

  • Gli ambienti Lisp possono essere in qualche modo più difficili da produrre binari. È necessario "scuotere" l'immagine per rimuovere i bit non necessari e, se non si esercita correttamente il programma durante tale processo, si potrebbero finire con errori di runtime in seguito . Al contrario, con Chez compiliamo un file di livello superiore che include tutti gli altri file necessari e il gioco è fatto.

Ho detto prima che abbiamo finito per usare Scheme in un numero di posti che inizialmente non intendevamo. Perché? Riesco a pensare a tre motivi dalla cima della mia testa.

Innanzitutto, abbiamo imparato a fidarci di Chez (e del suo sviluppatore, Cadence). Abbiamo chiesto molto dallo strumento ed è stato consegnato costantemente. Ad esempio, Chez ha storicamente avuto un numero banalmente piccolo di difetti e il suo gestore della memoria è stato molto, molto buono.

In secondo luogo, abbiamo imparato ad amare la performance che abbiamo avuto da Chez. Stavamo usando qualcosa che sembrava un linguaggio di scripting e ne stavamo ottenendo la velocità in codice nativo. Per alcune cose che non avevano importanza, ma non faceva mai male, e talvolta aiutava moltissimo.

In terzo luogo, abbiamo imparato ad amare l'astrazione che lo Schema potrebbe fornire. A proposito, non intendo solo macro; Intendo cose come chiusure, lambda, chiamate di coda, ecc. Una volta che inizi a pensare in questi termini, altre lingue sembrano piuttosto limitate al confronto.

Scheme è perfetto? No; è un compromesso. Innanzitutto, consente ai singoli sviluppatori di essere più efficaci, ma è più difficile per gli sviluppatori fare a vicenda il codice dell'altro perché i diagrammi che la maggior parte delle lingue hanno (ad esempio, per i loop) mancano nello Schema (ad esempio, ci sono un milione di modi per fare a per ciclo). In secondo luogo, c'è un gruppo molto più piccolo di sviluppatori con cui parlare, assumere, prendere in prestito, ecc.

Per riassumere, penso che direi: Lisp e Scheme offrono alcune funzionalità non ampiamente disponibili altrove. Questa capacità è un compromesso, quindi sarebbe meglio che abbia senso nel tuo caso particolare. Nel nostro caso, i fattori determinanti tra se usare Lisp o Scheme avevano più a che fare con funzionalità fondamentali (supporto della piattaforma, thread della piattaforma, compilazione di runtime, licenze di runtime) piuttosto che con funzionalità di linguaggio o libreria. Ancora una volta, nel nostro caso anche quello è stato un compromesso: con Chez abbiamo ottenuto le funzionalità di base che volevamo, ma abbiamo perso le ampie librerie degli ambienti commerciali di Lisp.

Inoltre, solo per ribadire: abbiamo guardato i vari Lisps e Schemi molto tempo fa; da allora si sono tutti evoluti e migliorati.


1
Caspita, deve essere stato un codice Delphi davvero orribile se in qualche modo è riuscito a eseguire 3-6 volte più lentamente di un'implementazione Lisp! :(
Mason Wheeler,

2
+1: La cosa più interessante di questo post è il fatto che sei passato da Lisp a Scheme dopo aver realizzato un grande progetto in Lisp. (O forse sono solo in agguato da troppo tempo su comp.lang.lisp.)
Larry Coleman,

25
"Wow, deve essere stato un codice Delphi davvero orribile se in qualche modo è riuscito a eseguire 3-6 volte più lentamente di un'implementazione Lisp!" Bene, lo considererò come il mio fallimento per non averlo spiegato meglio. L'implementazione di Lisp è stata in grado di trasformare le espressioni utente in espressioni Lisp - un processo banalmente facile - e quindi compilare le espressioni Lisp in codice nativo (con ottimizzazione completa). Questo è il significato della Decima Regola di Greenspun.
Michael Lenaghan,

1
Risposta fantastica! Lo sceglierò, almeno fino a quando non ne comparirà uno migliore :) Una domanda: dici che hai preso la decisione di andare con Chez Scheme in base allo stato del campo "molto tempo fa". Potresti specificare un anno?
SuperElectric

11
Quel punto, che l'implementazione di LISP è libera di compilare qualcosa in codice macchina, piuttosto che fare affidamento su un interprete, è sottile e abbastanza utile. Il libro "Let Over Lambda" sottolinea proprio questo perché il pacchetto regexp Common LISP portatile, che clona la sintassi regexp del PERL, supera PERL di un fattore significativo. PERL, in fondo, ha un interprete regexp. Il pacchetto Common LISP compila le regexps in codice.
John R. Strohm,

37

Di solito non mi piace incollare un link come risposta, ma ho scritto un articolo di blog proprio su questa cosa. Non è esaustivo, ma ottiene alcuni dei punti principali.

http://symbo1ics.com/blog/?p=729

Modifica : ecco i punti principali:

  1. ESISTENZA : Entrambe le lisps sono arrivate dopo un mucchio di altre lisps. Lo schema ha preso la via assiomatica minima. CL prese la via barocca.
  2. CASO : in genere lo schema fa distinzione tra maiuscole e minuscole. CL non lo è (sebbene possa essere). Questo a volte è mancato, ma la sua praticità è discussa (da me).
  3. NOMI : I nomi dei simboli in CL sono molte volte strani e confusi. TERPRI, PROGNecc. Lo schema di solito ha nomi molto sensibili. Questo è qualcosa che manca in CL.
  4. FUNZIONI : CL ha uno spazio dei nomi delle funzioni separato. Questo non è mancato in Scheme. Avere un singolo spazio dei nomi di solito consente una programmazione funzionale molto pulita, che è spesso difficile o scomoda in CL. Ma ha un costo --- a volte devi offuscare nomi come " list" a " lst" in Scheme.
  5. MACRO : mi manca di più le macro sporche di basso livello in Scheme. Sì, syntax-rulesva tutto bene e dandy fino a quando non vuoi davvero hackerare alcune cose. D'altra parte, le macro igieniche a volte mancano in CL. Non avere un modo standard per farli significa reinventare la ruota.
  6. PORTABILITÀ : Spesso il CL è più portatile, nonostante entrambe le lingue siano standardizzate. CL è più grande e quindi ci sono più funzionalità standard da usare senza librerie esterne. Significa anche che più cose dipendenti dall'implementazione possono essere fatte in modo portabile. Inoltre, Scheme soffre di avere trilioni di implementazioni, la maggior parte delle quali sono in qualche modo incompatibili. Questo rende CL molto desiderabile.
  7. BIBLIOTECHE : Molto legati al mio ultimo punto. Lo schema ha SRFI ma non è universalmente riconosciuto. Non esiste un modo portatile per lavorare con le biblioteche. CL d'altra parte ha dei modi. E Quicklisp è un dono di god (Xach) --- una sorta di repository di librerie da usare.
  8. ATTUAZIONE : il programma soffre di così tante implementazioni. Non esiste una vera implementazione canonica. CL d'altra parte ha alcune ottime implementazioni ad alte prestazioni o uso specifico (alte prestazioni: SBCL, commerciale: Allegro, incorporato: ECL, portatile: CLISP, Java: ABCL, ...).

Mentre ho parlato solo in prima persona un po 'sopra, dovrebbe essere chiaro cosa mi manca e cosa no.

[Mi scuso se sono troppo generici. Sembra che potresti desiderare dettagli molto più specifici. Ci sono alcuni dettagli nel post.]


che dire di un (davvero) breve riassunto del teaser? ^^
Dave O.

2
Si prega di includere i punti salienti. Le risposte dovrebbero essere indipendenti.

1
@Dave O. e @ Thorbjørn Ravn Andersen: aggiunto un riepilogo come richiesto. Grazie.
Quadrescenza

2
"La via barocca"! Che modo eccellente per dirlo.
Segna C

Il Lisp comune fa distinzione tra maiuscole e minuscole, ma converte il suo input in maiuscolo prima di valutarlo. Puoi ottenere lettere minuscole nei simboli citandole. Il problema del nome è perché Scheme si è sbarazzato dei vecchi nomi cattivi e CL no.
David Thornley,

25

Di recente ho iniziato un progetto a casa usando una libreria che ha una versione C e una versione Java. Volevo usare Lisp per il progetto e ho trascorso circa un mese vacillando tra l'utilizzo di Common Lisp, Scheme o Clojure. Ho una certa esperienza con tutti e tre, ma solo progetti di giocattoli. Ti racconterò un po 'della mia esperienza con ognuno di loro prima di dirti quale ho scelto.

La racchetta PLT ha un bel IDE che non solo ti consente di valutare le espressioni dall'editor, ma ti consente anche di digitare parentesi anziché parentesi, riportandole in parentesi dove appropriato. Racket ha anche un ampio set di librerie con l'installazione e ancora più disponibili per il download. Anche il debugger visivo è utile.

La mia implementazione Common Lisp (SBCL) non ha un IDE, ma è consuetudine con implementazioni CL open-source per utilizzare Emacs e SLIME. Questa combinazione può essere molto efficiente. Oltre alla possibilità di valutare le espressioni mentre le digiti nel file sorgente, c'è anche un REPL che ha tutti i comandi di modifica di emacs disponibili, quindi la copia del codice può andare in modo efficiente in entrambi i modi. Anche gli oggetti visualizzati nel buffer REPL possono essere copiati e incollati. Alt+(e Alt+)sono efficaci per gestire parentesi e rientri corrispondenti.

Tutte le funzionalità di Emacs sopra sono disponibili anche per Clojure. La mia esperienza di editing con Clojure è simile a quella di Lisp. L'interoperabilità Java ha funzionato bene e mi piacerebbe fare un progetto Clojure una volta maturato.

Sono stato in grado di accedere alla libreria usando tutti e tre (Common Lisp, Racket e Clojure), ma ho finito per scegliere Common Lisp per il progetto. Il fattore decisivo era che FFI era molto più facile da usare in Common Lisp. CFFI ha un ottimo manuale con codice di esempio e spiegazioni dettagliate di ciascun metodo. Sono stato in grado di racchiudere 20 funzioni C in un pomeriggio e da allora non ho più dovuto toccare il codice.

L'altro fattore era che ho più familiarità con Common Lisp che con Clojure o R6RS Scheme. Ho letto la maggior parte dei libri di Practical Common Lisp e Graham e mi sento a mio agio con Hyperspec. Non è ancora un codice molto "lispy", ma sono sicuro che cambierà man mano che acquisirò più esperienza.


Grazie per il dettaglio! Ti capisco correttamente che pensavi che FFI di SBCL fosse più facile da usare di quello di Clojure? In tal caso, ne sarei piuttosto sorpreso, dato che puoi semplicemente chiamare i metodi Java direttamente da Clojure senza doverli avvolgere. (O hai anche bisogno di chiamare il codice nativo?)
SuperElectric

6
@SuperElectric: La chiamata di metodi Java "integrati" da Clojure è banale; chiamare metodi Java che si trovano in una libreria scaricata: non così tanto. Ho davvero speso più tempo a prendere il percorso di classe e importare le linee giuste di quanto mi ci sia voluto per far funzionare il mio primo metodo C da SBCL con CFFI. Ma non sono un esperto di Java, quindi il tuo chilometraggio può variare.
Larry Coleman,

21

Programmo sia in CL che in Racket.

Sto sviluppando un sito Web ora in Common Lisp e ho scritto una suite di programmi interni per il mio precedente datore di lavoro in Racket.

Per il codice interno, ho scelto Racket (allora noto come Schema PLT) perché il datore di lavoro era un negozio di Windows e non riuscivo a farli pagare per LispWorks. L'unica buona implementazione CL open-source per Windows era (ed è tuttora) CCL, che richiede il supporto SSE nel processore. Il datore di lavoro, essendo economico, utilizzava l'hardware Stone Age. Anche se il datore di lavoro disponeva di hardware decente, l'unica libreria di conseguenza della GUI in Common Lisp è McCLIM, che funziona solo su Unix. Racket ha una buona libreria GUI che funziona sia su Unix che su Windows, il che è stato fondamentale per il successo del mio progetto.

Ho trascorso più di un anno a sopportare il primitivo editore DrRacket. EMACS non è stato in grado di trasformare la versione GUI di Racket, allora nota come MrEd, in una versione inferiore di Windows. Ho dovuto fare a meno di essere in grado di valutare l'espressione sul cursore con un solo tasto. Invece, ho dovuto selezionare manualmente l'espressione S, copiarlo, fare clic sulla finestra REPL (perché non è necessario premere il tasto per passare ad esso), quindi incollare l'espressione S. Ho anche dovuto fare a meno di un editor che potesse mostrarmi gli argomenti attesi della funzione o della macro che stavo usando. DrRacket non sostituisce SLIME.

Il datore di lavoro utilizzava un database proprietario con un'API XML complessa che richiedeva un sacco di informazioni apparentemente non necessarie per poter rispondere alla sua versione di una query SELECT. Ho deciso di utilizzare HTMLPrag sia per emettere XML a questa API, sia per analizzare le risposte. Ha funzionato alla grande.

Ho dovuto imparare il sistema macro "caso sintassi" troppo complicato di Racket per scrivere una macro che mi permettesse di interagire con l'API XML troppo complicata digitando moduli che sembravano SQL. Questa parte sarebbe stata molto più semplice se avessi DEFMACRO a mia disposizione. Tuttavia, il risultato finale è stato ancora senza soluzione di continuità, anche se ci sono voluti più sforzi per raggiungere.

Inoltre, ho dovuto fare a meno della macro LOOP di Common Lisp. Racket ha iniziato a fornire un'alternativa solo dopo che avevo scritto la maggior parte del codice e l'alternativa fa ancora schifo rispetto a LOOP (anche se il team di sviluppo di Racket insiste sul fatto che è meglio - hanno semplicemente torto). Ho finito per scrivere molti moduli LET che utilizzavano "car" e "cdr" per scorrere le liste.

Parlando di auto e cddr, niente è più frustrante dell'interpretazione di Scheme di (car '()) come errore. Ho sfruttato la distinzione tra maiuscole e minuscole di Racket e ho implementato CAR e CDR, che hanno la semantica di Common Lisp. Tuttavia, la separazione di '() e #f rende molto meno utile restituire' () come valore predefinito.

Ho anche finito per reimplementare UNWIND-PROTECT e ho inventato il mio sistema di riavvio per colmare il vuoto lasciato da Racket. La community di Racket deve imparare che i riavvii sono molto utili e facili da implementare.

La forma dei valori let di Racket era eccessivamente dettagliata, quindi ho implementato MULTIPLE-VALUE-BIND. Questo era assolutamente necessario, perché Racket richiede di ricevere tutti i valori che vengono generati, che li utilizzi o meno.

Successivamente, ho tentato di scrivere un client API XML eBay in Common Lisp, solo per scoprire che non ha niente come HTMLPrag. HTMLPrag è estremamente utile. Ho finito per fare quel progetto in Racket. Ho sperimentato le strutture di programmazione letterale di Racket, solo per scoprire che sono l'unico programmatore sulla Terra che trova il codice letterato correttamente scritto più difficile da modificare rispetto al codice ordinario, o codice letterale "commenti eccessivi" scritto in modo improprio.

Il mio nuovo progetto è stato realizzato in Common Lisp, che è stata la scelta giusta perché la comunità di Racket non crede nel parallelismo, che è essenziale per questo progetto. L'unica cosa che pensavo di potermi perdere da Racket erano le continuazioni. Tuttavia, sono stato in grado di fare ciò di cui avevo bisogno usando il riavvio e, in retrospettiva, probabilmente avrei potuto farlo con una semplice chiusura.


2
Non l'ho provato da solo, ma ho visto post sul blog di persone che usano il programma di racchette da riga di comando con Emacs. Ad esempio: bc.tech.coop/scheme/scheme-emacs.htm
Larry Coleman

5
In tutta onestà sembra che tu sia arrivato a Scheme che volesse scrivere CL invece di provare ad avvicinarti alle cose da un idiomatico POV Scheme. Ad esempio, lo schema non incoraggia la ricorsione piuttosto che l'uso di loop?
Slitta,

Lo schema @ArtB non solo incoraggia la ricorsione, ma la richiede , quindi ovviamente il progetto sopra menzionato ha usato molta ricorsione. E questo è servito solo per aggiungere la ripetizione (devi includere una copia della chiamata ricorsiva in ogni ramo di un condmodulo, per esempio) e bug (ho scritto correttamente il test di terminazione del loop quella volta?) Anche oggi, ho l'impressione che Racket è principalmente destinato a studenti e non a programmatori professionisti. Ogni volta che sento qualcuno oltre a me usarlo, usano il sublingua "Studente principiante" ed è per una lezione.
Getta via l'account

Se stai ripetendo il codice attraverso CONDs stai dicendo che hai solo bisogno di un'altra funzione?
Slitta

@ArtB Una funzione per chiamare la funzione loop con argomenti diversi? Sarebbe un po 'inutile. Vedi quel tipo di ripetizione nel codice Schema di chiunque. Ci sono anche esempi nel codice sorgente di Racket.
Getta via l'account

5

Lo schema è progettato pensando a una compilation separata. Di conseguenza, una potenza delle sue macro è spesso fortemente limitata, anche con le estensioni che consentono un defmacro in stile Lisp comune anziché un povero e limitato sistema macro igienico. Non è sempre possibile definire una macro che definisce un'altra macro, destinata ad un uso immediato in una riga di codice successiva. E tale possibilità è essenziale per l'implementazione di compilatori eDSL efficienti.

Inutile dire che le implementazioni di Scheme con solo macro igieniche R5RS sono a malapena utili per me, poiché il mio stile di metaprogrammazione non può essere adeguatamente tradotto in igiene.

Fortunatamente, ci sono implementazioni di Scheme (es. Racket) che non hanno questa limitazione.


1
Ciao, ho appena iniziato a bagnarmi i piedi con Scheme ultimamente usando Racket. Ti dispiacerebbe fornire un rapido esempio di utilizzo di macro non igieniche in Racket? Il tipo di macro disponibili sembra uno dei punti più discussi tra CL e Scheme.
orange80,

@ orange80, l'unico approccio è usare docs.racket-lang.org/mzlib/mzlib_defmacro.html E, naturalmente, in modalità R6RS c'è un modo meno restrittivo.
SK-logic,

@ SK-logic cosa stai facendo con le macro così poco antigeniche?
Slitta,

1
@ArtB, sto implementando eDSL come funzioni di compilazione che potrebbero fare molto con il loro AST di origine. L'igiene è un fastidio totale all'interno di tale approccio. Puoi dare un'occhiata a come funziona: github.com/combinatorylogic/mbase
SK-logic
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.