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.