2012-03-02 9 views
22

Tre lispy lingue homoiconic, Dylan, Julia e Seph tutti trasferiti fuori dalle principali parentesi - quindi una chiamata di funzione ipotetico Common Lisp che sarebbe simile:Cosa perderebbe Clojure passando da parentesi come Dylan, Julia e Seph?

(print hello world) 

sarà simile al seguente chiamata di funzione ipotetica

print(hello world) 

nelle tre lingue sopra menzionate.

Sono stati Clojure a percorrere questa strada - cosa avrebbe dovuto sacrificare per arrivarci?

Ragionamento: A parte le incredibili pigri strutture dati funzionali in Clojure, e il miglioramento della sintassi per mappe e seguenti del regolamento provvisorio, il supporto per la lingua per la concorrenza, la piattaforma JVM, le attrezzature e la comunità impressionante - la cosa distintivo sul fatto che sia 'un LISP' sta conducendo una parentesi che dà omoiconicità che fornisce macro che forniscono l'astrazione della sintassi.

Ma se non hai bisogno di parentesi tonde - perché le hanno? Gli unici argomenti che posso pensare per il loro mantenimento sono

(1) riutilizzando strumento di supporto in emacs

(2) spingendo la gente a 'pensare in LISP' e non cercare di trattarlo come un altro linguaggio procedurale)

+6

Una grande parte del estetica Lisp è il parseability banale e usabilità come dati del codice; ne perderai un po '. – zmccord

+0

L'applicazione di funzione è solo una delle tante possibili forme. Stai proponendo di trattarli in modo diverso? Clojure ha già fatto una cosa terribile, abolendo le cellule. Andare oltre rovinerebbe completamente la lingua. –

+3

Vedere anche http://stackoverflow.com/questions/643892/fixing-lisp-syntax. La domanda mi ricorda uno sviluppatore Pascal che sapevo che, di fronte all'uso di C, desiderava un set di macro che rendesse il C più simile a Pascal. Penso che ci sia sempre la tentazione di ridurre il tuo disagio con qualcosa di nuovo costringendolo ad essere più familiare. Eppure a volte è meglio per te avvicinarti a qualcosa di diverso a modo suo. – user100464

risposta

13

macro scrittura sarebbe diventato molto più difficile in quanto la struttura non sarebbe più semplice che ci si bisogno di un altro modo per codificare in cui iniziano le espressioni e smettere di utilizzando alcuni simbolo sintattico per segnare l'inizio e la fine di espressioni per possibile write codice che genera le espressioni forse si potrebbe risolvere questo problema con l'aggiunta di qualcosa di simile a un ( per segnare l'inizio dell'espressione ...

in una prospettiva completamente diversa, vale la pena guardare questo video su the difference between familiar and easy fare lische sintassi più familiare non renderà più facile l'apprendimento a e potrebbe renderlo fuorviante se sembra molto simile a qualcosa che non è.

anche se non sei affatto d'accordo, quel video vale davvero la pena.

23

Il semplice spostamento delle parentesi di un atomo per le chiamate di funzione non sarebbe sufficiente per soddisfare chiunque; la gente si lamenterà della mancanza di operatori di infisso, blocchi di inizio/fine ecc. Inoltre, probabilmente dovresti introdurre virgole/delimitatori in tutti i tipi di posti.

Dai loro che e i macro saranno molto più difficili solo per scrivere correttamente (e sarebbe probabilmente ancora più difficile scrivere macro che sembrano e funzionano bene con tutta la nuova sintassi che hai introdotto in quel momento). E i macro non sono qualcosa che è una caratteristica piacevole che puoi ignorare o rendere molto più fastidioso; l'intera lingua (come qualsiasi altro Lisp) è costruita proprio sopra di loro. La maggior parte delle cose "user-visible" che sono in clojure.core, inclusi let, def, defn ecc sono macro.

+0

:) Accetto che non sia possibile rendere felici le persone. Suppongo che tu manterrai i macro, e penso che tu stia dicendo "beh, dovresti riscrivere tutte queste macro linguistiche core". Ma il punto è che qualcuno ha deciso che ne è valsa la pena su almeno tre lingue diverse. La mia domanda non era il perché ma il cosa. – hawkeye

0
Were Clojure to go down this path - what would it have to sacrifice to get there? 

Il sacrificio sarebbe la sensazione/mentale-modali di scrivere codice con la creazione di Lista Lista Lista .. o più tecnicamente "a scrivere l'AST direttamente".

NOTA: Ci sono anche altre cose che saranno scarificate come menzionato in altre risposte.

2

Ho usato per codificare C/C#/Java/Pascal, quindi sottolineo con la sensazione che il codice Lisp sia un po 'alieno. Tuttavia questa sensazione dura solo poche settimane - dopo un periodo di tempo abbastanza breve, lo stile Lisp si sentirà molto naturale e inizierai a rimproverare altre lingue per la loro sintassi "irregolare" :-)

C'è una buona ragione per la sintassi Lisp. Le parentesi principali rendono il codice più semplice da analizzare e leggere, raccogliendo sia una funzione che le espressioni che costituiscono gli argomenti in un unico modulo.

E quando si manipolano codici/utilizzare macro, sono queste le forme che contano: questi sono gli elementi costitutivi di tutto il codice. Quindi ha fondamentalmente senso mettere le parentesi in un posto che delimita esattamente queste forme, piuttosto che lasciare arbitrariamente il primo elemento al di fuori della forma.

1

La filosofia del "codice è dati" è ciò che rende possibile la metaprogrammazione affidabile. Confronta con Perl/Ruby, che hanno una sintassi complessa, i loro approcci alla metaprogrammazione sono affidabili solo in circostanze molto limitate. La metaprogrammazione Lisp è così perfettamente affidabile che il nucleo del linguaggio dipende da esso. La ragione di ciò è la sintassi uniforme condivisa dal codice e dai dati (la proprietà dell'omoiconicità). Le espressioni S sono il modo in cui questa uniformità viene realizzata.

Ciò detto, ci sono casi in Clojure dove implicavano parentesi è possibile:

Ad esempio i seguenti tre espressioni sono equivalenti:

  1. (primo (riposo (riposo [1 2 3 4 5 6 7 8 9])))
  2. (-> [1 2 3 4 5 6 7 8 9] (riposo) (riposo) (primo))
  3. (-> [1 2 3 4 5 6 7 8 9 ] resto di riposo prima)

Si noti che nel terzo la macro -> è in grado in questo contesto di dedurre le parentesi e quindi di lasciarle fuori. Ci sono molti casi speciali come questo. In generale, il design di Clojure sbaglia sul lato di una parentesi minore. Vedi ad esempio la controversa decisione di lasciare la parentesi in cond. Clojure è molto guidato e coerente su questa scelta.

13

non avresti bisogno di sacrificare nulla. c'è un approccio molto attentamente ponderata da david wheeler che è completamente trasparente e compatibile, con pieno supporto per le macro ecc

19

(credito alla risposta di Andrew Cooke, che ha fornito il link per Wheeler e di "Readable Lisp S-expressions Project" di Gloria)

Il il collegamento sopra è un progetto destinato a fornire una sintassi leggibile per tutte le lingue basate su espressioni S, incluso Scheme e Clojure. La conclusione è che si può fare : c'è un modo per avere un Lisp leggibile senza le parentesi.

Fondamentalmente ciò che il progetto di David Wheeler fa è aggiungere zucchero sintattico ai linguaggi di tipo Lisp per fornire una sintassi più moderna, in modo da non interrompere il supporto di Lisp per i linguaggi specifici del dominio. I miglioramenti sono opzionali e retrocompatibili, quindi puoi includerne il più o il meno che vuoi e mescolarli con il codice esistente.

Questo progetto definisce tre nuovi tipi di espressione:

  • Riccio-infisso-espressioni. (+ 1 2 3) diventa {1 + 2 + 3} in ogni luogo in cui si desidera utilizzare gli operatori di infissi di qualsiasi livello. (Esiste un caso speciale che deve essere gestito con attenzione se l'espressione in linea utilizza diversi operatori, come {1 + 2 * 3} - sebbene {1 + {2 * 3}} funzioni come previsto).
  • Espressioni neoteric. (f xy) diventa f (xy) (non richiede spazio tra il nome della funzione e i relativi parametri)
  • Espressioni dolci. I genitori di apertura e chiusura possono essere sostituiti con (facoltativo) indentazione semantica simile a pitone. Le espressioni dolci possono essere mescolate liberamente con le espressioni s parentesi tradizionali.

Il risultato è un codice conforme Lisp ma molto più leggibile. Un esempio di come il nuovo zucchero sintattico migliora la leggibilità:

(define (gcd_ a b) 
    (let (r (% b a)) 
     (if (= r 0) a (gcd_ r a)))) 

(define-macro (my-gcd) 
    (apply gcd_ (args) 2)) 

diventa:

define gcd_(a b) 
    let r {b % a} 
     if {r = 0} a gcd_(r a) 

define-macro my-gcd() 
    apply gcd_ (args) 2 

Nota come la sintassi è compatibile con le macro, che era un problema con previous projects that intended to improve Lisp syntax (come descritto da Wheeler e Gloria) . Poiché è solo zucchero, la forma finale di ogni nuova espressione è un'espressione s, trasformata dal lettore di lingue prima che le macro vengano elaborate, quindi le macro non richiedono alcun trattamento speciale. Pertanto il progetto "Lisp leggibile" preserva l'omoiconicità, la proprietà che consente a Lisp di rappresentare il codice come dati all'interno del linguaggio, che è ciò che gli consente di essere un potente ambiente di meta-programmazione.

+2

se sei innervosito, mi ha sempre colpito il fatto che racket (uno schema che supporta più "lingue") sarebbe un buon posto per implementarlo - https://en.wikipedia.org/wiki/Racket_features#Language_Extensions –

3

Avresti Mathematica. Mathematica accetta chiamate di funzione come f[x, y, z], ma quando si esamina ulteriormente, si trova che f[x, y, z] è in realtà zucchero sintattico per un elenco in cui il Head (elemento 0) è f e (elementi da 1 a N) è {x, y, z}. Puoi costruire chiamate di funzione da liste che assomigliano molto alle S-espressioni e puoi scomporre le funzioni non valutate in elenchi (Hold impedisce la valutazione, proprio come quote in Lisp).

ci possono essere differenze semantiche tra Mathematica e Lisp/Schema/Clojure, ma la sintassi di Mathematica è la dimostrazione che è possibile spostare la parentesi sinistra sopra da un atomo e ancora interpretarlo sensibilmente, costruire il codice con le macro, ecc

La sintassi è piuttosto semplice da convertire con un preprocessore (molto più facile della semantica). Probabilmente potresti ottenere la sintassi che desideri attraverso una sottoclasse intelligente di Clojure's LispReader. C'è anche lo a project che cerca di risolvere le parentesi sconnesse di Clojure sostituendole tutte con parentesi quadre. (E 'incredibile la mia mente che questo è considerato un grosso problema.)