Clojure vs altri Lisp [chiuso]


93

L'intento della mia domanda non è quello di iniziare una guerra con le fiamme, ma piuttosto di determinare in quali circostanze ogni lingua è "lo strumento migliore per il lavoro".

Ho letto diversi libri su Clojure ( Programming Clojure , Practical Clojure , The Joy of Clojure e l'edizione Manning Early Access di Clojure in Action ) e penso che sia un linguaggio fantastico. Attualmente sto leggendo Let Over Lambda che si occupa principalmente di macro Common Lisp e, anch'esso, è un linguaggio molto interessante.

Sono non un esperto di Lisp (più di un novizio), ma questa famiglia di linguaggi mi affascina, così come la programmazione funzionale, in generale.

Vantaggi di Clojure (e svantaggi di "altri"):

  • Funziona su JVM.

    • La JVM è un ambiente linguistico molto stabile e ad alte prestazioni che soddisfa abbastanza bene il sogno di Sun di "Scrivi una volta, esegui [quasi] ovunque". Posso scrivere codice sul mio Macbook Pro, compilarlo in un file JAR eseguibile e quindi eseguirlo su Linux e Microsoft Windows con pochi test aggiuntivi.

    • La JVM (Hotspot e altre) supporta la garbage collection di alta qualità e la compilazione e l'ottimizzazione just-in-time molto performanti. Dove solo pochi anni fa ho scritto tutto ciò che doveva funzionare velocemente in C, ora non esito a farlo in Java.

    • Modello standard, semplice, multithreading. Common Lisp ha un pacchetto multithreading standard?

    • Spezza la monotonia di tutte quelle parentesi con [], {}e #{}, sebbene gli esperti di Common Lisp probabilmente mi diranno che con le macro del lettore, puoi aggiungerle a CL.

Svantaggi di Clojure :

  • Funziona su JVM.
    • Nessuna ricorsione o continuazione della coda. Common Lisp supporta le continuazioni? Scheme richiede supporto per entrambi, credo.

Vantaggi degli altri (Common Lisp, in particolare) (e svantaggi di Clojure):

  • Macro del lettore definibili dall'utente.

  • Altri vantaggi?

Pensieri? Altre differenze?


15
personalmente mi piace un tipo di parentesi;) sembra un codice "più pulito"
Moe

3
Da quello che ho letto sulla tua lista dei vantaggi immagino che forse ti potrebbe piacere anche Erlang www.erlang.org
Peer Stritzinger

4
Clojure supporta la ricorsione della coda esplicita tramite la forma speciale "recur". Ciò ti consente di ottenere tutti i vantaggi della ricorsione della coda, a condizione che tu lo richieda esplicitamente (l'unica eccezione è che attualmente non supporta le ricorsioni reciproche della coda tra più funzioni).
mikera

1
Clojure supporta anche le continuazioni, almeno nel senso di "stile di passaggio di continuazione". Hai ragione sul fatto che non ha continuazioni di prima classe. vedi stackoverflow.com/questions/1173133/continuations-in-clojure
mikera

@mikera: ricorsione della coda su una funzione. Due funzioni che si chiamano a vicenda devono essere eseguite con il "trampolino elastico", che è un po 'fastidioso (ma elegante a modo suo :-)).
Ralph

Risposte:


52

Il mio elenco personale di motivi per preferire Clojure ad altri Lisp (ps penso ancora che tutti i Lisp siano fantastici!):

  • Funziona sulla JVM - quindi ottiene l'accesso automatico alla fantastica ingegneria nella stessa JVM (algoritmi avanzati di raccolta dei rifiuti, ottimizzazione JIT HotSpot ecc.)

  • Interoperabilità Java molto buona: fornisce compatibilità con la vasta gamma di librerie nell'ecosistema del linguaggio Java / JVM. Ho usato Clojure come linguaggio "collante" per collegare diverse librerie Java con buoni risultati. Poiché sviluppo anche molto codice Java, è utile per me che Clojure si integri bene con gli strumenti Java (ad esempio, uso Maven, Eclipse con il plug-in Counterclockwise per il mio sviluppo Clojure)

  • Bella sintassi per vettori [1 2 3], mappe {:bob 10, :jane 15}e set #{"a" "b" "c"}: considero questi strumenti piuttosto essenziali per la programmazione moderna (oltre agli elenchi ovviamente!)

  • Personalmente mi piace l'uso delle parentesi quadre per le forme vincolanti: ad esempio (defn foo [a b] (+ a b)), penso che renda il codice un po 'più chiaro da leggere.

  • Enfasi sulla programmazione pigra e funzionale con strutture dati persistenti e immutabili - in particolare tutta la libreria Clojure di base è progettata per supportare questa impostazione predefinita

  • Eccellente implementazione STM per concorrenza multi-core. Credo che Clojure abbia la migliore storia di concorrenza di qualsiasi lingua al momento (guarda questo video per ulteriori elaborazioni dallo stesso Rich Hickey )

  • È un Lisp-1 (come Scheme), che personalmente preferisco (penso che in un linguaggio funzionale abbia senso mantenere funzioni e dati nello stesso spazio dei nomi)


2
+1 per STM. Di per sé è sufficiente per giustificare l'uso di Clojure.
André Caron

2
È ancora possibile ottenere STM utilizzando la libreria CL-STM.
Mike Manilone

2
@ AndréCaron solo se ne hai bisogno.
rightfold

Se volessi scrivere una semplice webapp e ospitarla, diciamo, un host economico da $ 5 al mese, ovviamente non è possibile con Clojure a causa della JVM, giusto?
Esatonico

@Hexatonic Non ho molta esperienza ma è difficile credere che una macchina in uso in questi giorni non avrebbe una JVM.
MasterMastic

25

Tieni presente che Clojure è un linguaggio e un'implementazione (di solito sulla JVM). Common Lisp è un linguaggio con più di dieci diverse implementazioni. Quindi abbiamo una mancata corrispondenza di categoria proprio qui. Potresti ad esempio confrontare Clojure con SBCL.

Generalmente:

  • una versione di Common Lisp viene eseguita su JVM: ABCL

  • la maggior parte delle altre implementazioni Common Lisp non lo fanno

  • la maggior parte delle implementazioni CL ha capacità multitasking, una libreria fornisce un'interfaccia comune

  • Common Lisp ha la sintassi per gli array. La sintassi per altri tipi di dati può essere scritta dall'utente e viene fornita da varie librerie.

  • Common Lisp non supporta né l'ottimizzazione delle chiamate di coda né le continuazioni. Le implementazioni forniscono il TCO e le librerie forniscono una qualche forma di continuazione.


24

Una differenza importante tra Clojure e Common Lisp è che Clojure è più prescrittivo sulla programmazione funzionale. La filosofia, gli idiomi e in una certa misura i linguaggi / le biblioteche di Clojure incoraggiano fortemente e talvolta insistono sul fatto che si programma in modo funzionale (senza effetti collaterali, nessuno stato mutevole).

Common Lisp supporta sicuramente la programmazione funzionale, ma consente anche lo stato mutevole e la programmazione imperativa.

Naturalmente, ci sono una serie di vantaggi per la programmazione funzionale, nell'area della concorrenza e altro. Ma a parità di condizioni, è anche utile poter scegliere quale approccio utilizzare per ogni situazione. Clojure non proibisce completamente la programmazione imperativa, ma è meno accomodante di quello stile rispetto al Common Lisp.


3
@Charlie Flowers: Credo che in Common Lisp sia possibile programmare in uno stile "puramente funzionale" (supporto persistente della struttura dei dati, ecc.), Ma richiede disciplina. Corretta?
Ralph

2
Solo un chiarimento su "nessun effetto collaterale, nessuno stato mutabile" - Clojure ha uno stato mutabile (ref, atomi, agenti ecc. Sono tutti mutabili) ma richiede che tu acceda in modo controllato (cioè tramite i meccanismi STM e le relative transazioni semantica di aggiornamento)
mikera

5
@mikera: tranne per il fatto che Clojure si basa sull'uso di librerie Java per essere utilizzabili, e tutte quelle librerie richiedono uno stile imperativo e sono piene di effetti collaterali. Ho scoperto che gli attacchi con Java sono un regalo avvelenato ...
André Caron

1
@Andre - certo, se decidi di utilizzare una libreria che richiede stato mutabile e semantica imperativa, devi gestirla. Questo non è diverso da se si accedeva a tale libreria da qualsiasi altra lingua. Ma hai due opzioni decenti: a) Non usare tali librerie: puoi scrivere codice perfettamente buono in puro Clojure oppure b) racchiudere la complessità dell'interfacciamento con queste librerie in una bella interfaccia funzionale in stile Clojure, che di solito è facile con macro o agenti, ecc. In generale, ho trovato la capacità di sfruttare le librerie Java un vantaggio molto maggiore di quanto non sia un problema.
mikera

4
@mikera: le biblioteche hanno un vantaggio. Sto solo sottolineando che l'uso delle librerie Java (questo è uno degli obiettivi primari di Rich Hickey per il linguaggio) va davvero contro l'aspetto "più funzionale di altri lisps" di Clojure. Il mio commento voleva dire: "a meno che tu non riscriva / impacchi queste librerie, otterrai un codice dall'aspetto imperativo e non trarrai vantaggio dalle parti più belle di Clojure".
André Caron

10

Ecco un buon video con un confronto tra Scheme (principalmente Racket) e Clojure .

Per essere onesti, Racket ha lo zucchero di sintassi (materiale aggiuntivo per i lettori) anche per i tipi di dati (#hash, #, parentesi quadre, ecc.)

Inoltre, l'unico modo di Clojure per effettuare una chiamata di coda corretta è usare recur, questo è lo svantaggio della compilazione in JVM.

Nota che recurè l'unico costrutto di loop che non consuma stack in Clojure. Non esiste un'ottimizzazione delle chiamate di coda e l'uso di chiamate automatiche per il loop di limiti sconosciuti è scoraggiato. recurè funzionale e il suo utilizzo in tail-position è verificato dal compilatore. ( Forme speciali ).


Link è morto, immagino.
nawfal

1
@nawfal Penso di averlo risolto
Daniil

6
Link è morto (di nuovo?)
Butta via Account

1
Sembra che il video su quel collegamento possa essere trovato qui: vimeo.com/22675078 .
PIL2

C'è anche trampolineper le chiamate di coda.
HappyFace
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.