2009-03-13 5 views
15

Essendo un novizio di Lisp mi chiedo se la sintassi Lisp possa essere "riparata"?Fixing Lisp Sintassi

Alcuni dicono che la sintassi in Lisp è uno dei suoi maggiori punti di forza. Non capisco questo.

Non è possibile sostituire le parentesi "ovvie" con una combinazione di spazi bianchi, nuove linee e rientri? Proprio come in Python?

Mi sembra che le parentesi siano i caratteri più utilizzati nel codice Lisp. Mi chiedo se sia vero - ma se lo è, non è questo un suggerimento, che c'è qualche ridondanza nella sintassi?

C'è una risposta semplice alla domanda: perché tante parentesi?

Ad esempio:

(defun factorial (x) 
    (if (= x 0) 
     1 
     (* x 
      (factorial (- x 1))))) 

Perché non:

defun factorial (x) 
    if (= x 0) 
    1 
    * x 
     factorial 
     - x 1 

esempio chiudere le parentesi alla fine della riga e aprirle sempre su nuove linee. Solo il 1 sarebbe ambiguo - è 1 o (1) - ma potremmo introdurre un'eccezione - i token singoli non sono "elencati".

Potrebbe funzionare?

Edit:

Grazie a tutti! Vedo ora ci sono alcuni links al lispin site.

+1

cosa si sta parlando non è la sintassi, è la punteggiatura. La sintassi sarebbe (a b c) o (a c b) la decisione del tipo. – vrdhn

+1

Il mio regno per una parola chiave "altro"! – marcus

+2

@marcus È sempre possibile utilizzare defmacro per un if/else che accetta un'altra parola chiave; tutto quello che devi fare è non espandere mai il parametro 'else', solo le due forme del corpo. – Skrylar

risposta

12

Cosa suggerisci sembra essere stato implementato in Lispin

Edit:sindikat punti nei commenti qui sotto che il link non è più valido. Ecco l'ultima versione valida del sito dall'archivio Web: http://wayback.archive.org/web/20080517144846id_/http://www.lispin.org/

+2

Interessante ... è il contrario vero, ad es. c'è una variante di Python che usa parentesi invece di indentazione? –

+2

sono sicuro che ce ne sarebbe uno se Python avesse anche 50 anni ... :) –

+0

"c'è una variante di Python che usa le parentesi" - probabilmente. Basta guardare indietro nella storia per una variante più semplice di Lisp predating Common Lisp. Naturalmente, mancherà il supporto della grande libreria che contiene le moderne distribuzioni Python. – Aaron

5

Potrebbe funzionare. Si chiama Dylan.

+0

Dylan manca del codice è parte dati. –

+4

invece lo direi: "si può provare, si chiama dylan" ... :) –

1

di rispondere alla domanda del perché:

E 'uso principale per quanto ne so è la leggibilità, in modo che le persone che guardano il codice in grado di decifrare più facilmente.

Spero che aiuti.

27

E 'stato fatto un sacco di volte (un preprocessore a venti linee < farà miracoli). Ma c'è anche un vantaggio nel farli esplicitare. Spinge a casa il parallelismo tra codice e dati, e in un certo senso ti porta fuori dal tipo di pensiero che ti fa sembrare noioso.

Si potrebbe (per un esempio analogo) prendere un linguaggio orientato agli oggetti e rimuovere tutto il raggruppamento sintattico dei metodi in classi (in modo che diventino, in effetti, funzioni sovraccariche). Questo ti permetterebbe di guardarlo più come se fosse un linguaggio imperativo diretto, ma qualcosa andrebbe perso.

Quando si guarda a lisca si suppone a pensare "Tutto è una lista. Ommm"

(Beh, ok, il "Ommm" è opzionale).

3

Ci sono due tipi di persone: ™: coloro che elaborano le informazioni mediante la macchina stack incorporata nel loro cervello e coloro che la consumano in grandi blocchi o blocchi. Questi gruppi sono reciprocamente incompatibili l'uno con l'altro; leggono libri diversi, hanno stili di scrittura diversi e, soprattutto, scrivono codice in diversi linguaggi di programmazione. Appartengo al secondo gruppo; tuttavia, conosco molti colleghi programmatori del primo gruppo.

Per le persone del primo gruppo, non c'è assolutamente nulla di sbagliato nelle clausole nidificate e nei sottopunti; afferrano la ricorsione naturalmente; guardano il codice lentamente, istruzione per frase, riga per riga e pila macchina nel loro cervello continua a contare parentesi e parentesi a livello subconscio. La sintassi Lisp è piuttosto naturale per loro. Inferno, probabilmente hanno inventato le macchine stack e la lingua Forth. Ma mostrali, diciamo, Python (oh noes!), E guarderanno impotenti ai fogli di codice, incapaci di capire perché questi stupidi blocchi di codice sono lasciati aperti, senza istruzioni di chiusura corrispondenti.

Per noi, ragazzi poveri del secondo gruppo, non c'è altra opzione che le istruzioni di codice di gruppo nei blocchi e visualizzarli visivamente. Guardiamo allo schermo pieno di codice, prima notiamo la struttura su larga scala, quindi separiamo funzioni o metodi, quindi gruppi di istruzioni all'interno di questi metodi, quindi linee e istruzioni, dall'alto verso il basso. Non possiamo pensare linearmente; abbiamo bisogno di limiti visivi e politiche di indentazione pulite. Quindi, non possiamo piegarci a lavorare con Lisp; per noi, è un disordine irregolare di parole chiave e parentesi sciocche.

La maggior parte dei linguaggi di programmazione è compatibile con entrambi i modi di pensare (quei "blocchi" ci sono per la ragione). Eccezioni notevoli sono Lisp e Forth, che sono solo il primo gruppo e Python, che è solo il secondo gruppo. Non penso che tu debba adattare Lisp al tuo modo di pensare se fai parte del secondo gruppo. Se hai ancora bisogno di un linguaggio funzionale, prova Haskell. È un linguaggio funzionale progettato per persone che pensano in blocchi, non in pile.

+2

questa teoria suona bene, ma io sono un tipo di blocco e sono più produttivo in lisp. Ho anche delle regole forti su come indentare dichiarazioni variabili libere, espressioni booleane, ecc ... per aiutare il mio parser di blocchi quando torno al codice più tardi. –

+2

Lisp ha uno stile di indentazione standard che ti dà i tuoi blocchi. Non vedrai più le parentesi dopo poco tempo. – Svante

+3

Non lo compro, penso che qualsiasi persona intelligente possa passare tra i due con un problema minimo. – temp2290

28

Cambierete idea dopo aver scritto un paio di macro.

+0

QUESTA risposta dovrebbe essere accettata come risposta (anche se è piuttosto concisa). I macros sono ESATTAMENTE perché i paren sono così fantastici. Dato che la domanda era "rimuovendo i parens si rompono le labbra?", La risposta può essere trovata qui. –

+1

puoi avere macro sistemi altrettanto potenti per una sintassi più complessa (vedi la lavagna come esempio), ma le macro sono abbastanza complesse usando semplici elenchi che denotano programmi, quindi pochissime persone si occupano di potenti macrosistemi che lavorano su AST di linguaggi ricchi di sintassi. –

+0

@Attila, la potenza e la semplicità non sono inversamente correlate. Punto preso però. – dnolen

5

Anche Paul Graham, un fautore vocale per la famiglia Lisp delle lingue, ha rimosso alcune parentesi dal suo proprio dialetto Arc:

Nota per gli hacker Lisp: Se siete abituati al tradizionale Lisp cond operatore , questo se equivale alla stessa cosa, ma con meno parentesi . Per esempio.

(cond (a b) 
     (c d) 
     (t e)) 

diventa

(if a b 
    c d 
    e) 

(dal Arc Tutorial)

+3

Il problema è che le parentesi forniscono il raggruppamento e questo manca all'IF di Graham. Con COND I posiziono il cursore tra due clausole e premi m-t (cioè: exchange sexp) e vengono scambiate. Posso spostare la clausola su o giù. –

+0

@Rainer, il mio più grande programma Lisp era un simulatore quantistico e un compilatore. Piccolo. Quindi non posso nemmeno decidere quale preferisco. Posso tuttavia affermare che il tuo screencast "Dominio specifico della lingua" è stato stimolante. È stato un piacere vedere un hacker Lisp con esperienza al lavoro. –

+0

@Frank Questo è per il feedback positivo. Informazioni su 'decidere'. Fa parte dell'esperienza Lisp. Con alcuni esperimenti impari ad acquisire un po 'di' gusto 'su ciò che sembra buono E si sente bene. 'Feels' significa, cosa è facile da manipolare con l'editor di testo E il sistema Lisp. Il codice è dati. Il dato è codice. –

0

Leggendo i link, ho trovato questo - Indentation-sensitive syntax - c'è anche il modulo Guile, che implementa questa sintassi, in modo si potrebbe provare direttamente.

Un bel promising Lisp il dialetto (arco) può essere trovato here. (Immagino che uno dovrebbe prima del codice reale vedere come ci si sente)

+2

arc non è promettente, è solo un altro ... –

17

"Forse questo processo dovrebbe essere considerato un rito di passaggio per gli hacker Lisp."

- Steele e Gabriel, "The Evolution of Lisp", 1993

9

Diverse volte ho confrontato codice Lisp e codice equivalente in altre lingue codice Lisp ha più parentesi, ma se si contano tutte raggruppamento. caratteri [] {}() in altre lingue, Lisp ha meno parenti di tutti. Non è più prolisso: è più coerente!

Se visto da questo punto di vista, il "problema" è semplicemente che Lisp ne usa uno tipo di costrutto (elenchi) per ogni cosa e questa è la base per i suoi macro, il suo sistema di oggetti, un paio dei suoi costrutti di looping più potenti e così via. Quello che vedi come un problema di stile minore (le parentesi sembrano più fredde?) è reale è un segno del potere della lingua.

Detto questo, Lisp è tutto per dare potere al programmatore. Se vuoi, scrivi il tuo dialetto personale che ti consente di farlo. Lisp (a differenza di alcune lingue che potrei menzionare!) Riguarda esclusivamente la potenza del programmatore, quindi usalo. Se riesci a farlo funzionare, forse decollerà. Non penso che lo farà, ma non c'è niente che ti impedisca di provare, e imparerai molto in entrambi i modi.

6

Il punto di lisp "sintassi" è la sua non esistenza. Un'espressione s è un albero di identità, in cui la struttura ad albero è denotata da parents (e indentazione). Vale la pena notare che i sexps dovevano essere solo una rappresentazione di basso livello, ma la gente finì per apprezzarlo di più e continuò ad usarlo.

Nei un'espressione significa motore di esecuzione è incredibilmente flessibile in lisp ed è anche sensibile al contesto.

In altre lingue, il livello di sensibilità al contesto è molto più basso e l'insieme di elementi costitutivi che è possibile utilizzare per creare le proprie astrazioni è molto meno estensibile. Pertanto, la sintassi speciale che denota i pochi costrutti dati è adatta all'immagine.

In lisp, posso cambiare il significato di tutto, anche in un modo sensibile al contesto. Avere una sintassi speciale per alcuni costrutti predefiniti sarebbe sciocco perché potrei finire usando il mio "se", o le mie chiusure specializzate, ecc. E se il mio nuovo "se" avesse bisogno di 4 argomenti (ad esempio per raggruppare certe se di un programmare e dire ad alcuni gruppi di fallire o avere successo in certe situazioni)? Come dovrei estendere la sintassi del 'if' predefinito? È molto più semplice ricorrere all'AST (sexp), ma allora perché preoccuparsi di una sintassi particolare?

Si noti inoltre che l'utilizzo di un editor come emacs rende molto semplice la modifica di un albero in modo strutturato. Ad esempio, avere una chiave per trasporre due nodi in un albero è ugualmente utile per scambiare dichiarazioni di variabili e scambiare due istruzioni in un blocco di programma (suggerimento: ecco perché gli "extra" parens sono utili in let, cond, ecc.).

Quindi, questo è il ragionamento per cui la non sintassi Lisp è così attraente per molte persone che si sono abituati all'idea di estendere il linguaggio invece di piegare il problema di montare un set predefinito di strumenti .. . ma ciò non significa che lo zucchero di sintassi non venga usato per i costrutti dati dall'utente!

Alcuni esempi di sintassi definita dall'utente che usiamo:

  • cl-syntax-sugar - l'estensione più notevole è il [] parentesi utilizzati per piccole chiusure in cui non si desidera dare un nome variabili della chiusura
  • cl-quasi-quote - in particolare la sintassi <xml > per incorporare la generazione xhtml nel codice lisp (si noti che questa sintassi è fornita da una libreria dell'utente e può essere abilitata in modo sensibile al contesto)
+3

Lisp di solito ha una sintassi a due stadi. Sintassi dei dati con le espressioni S e la sintassi del programma rispetto alle espressioni s. Entrambi sono sintassi - che riguarda la struttura di "frasi" valide (programmi) in linguaggio (Lisp). –

1

La mia opinione personale su questo è: non usare newlines e indentation come separatori "impliciti" (non mi piace neanche il raggruppamento implicito per precedenza degli operatori, ma questo è un argomento diverso, sebbene correlato).

Esempio: questo Python valido? Fa quello che ti aspetti?

if foo < 0 : 
    bar 
    else : 
    baz 
quuz 

ho un po 'proposta: potremmo usare un preprocessore per far rientrare automaticamente il codice Python, mettendo caratteri speciali nel codice che indicare dove una dichiarazione inizia e finisce. Che ne dici di parentesi per questo?

0

Si potrebbe dare un'occhiata a Clojure. Parentesi minori ma più sintassi da ricordare.

0

Ho provato e scritto un paio di sintassi che si basano sui rientri. Ai migliori risultati l'intera sintassi ha cambiato la sua natura e quindi la lingua è passata dall'uno all'altro. Una buona sintassi basata su indentazione non è più nulla vicino alla lisp.

Il problema di attribuire un significato sintattico all'indentazione non deriva dagli idioti e dal confronto tra spazio pubblico e spazio bianco. Tokenizzare non è un problema dato che leggere le newline e gli spazi non dovrebbe essere più difficile di qualsiasi altra cosa. La cosa più difficile è determinare quale indentazione dovrebbe significare dove appare e come aggiungere significati senza sintassi troppo complicata per la lingua.

Sto iniziando a considerare la sintassi in stile lisp originale è meglio dopo aver minimizzato la quantità di parentesi con una programmazione intelligente. Questo può essere fatto, non così facilmente nelle attuali implementazioni lisp, ma nelle future implementazioni lisp può essere fatto più facilmente. È veloce e semplice da analizzare quando ci sono solo un paio di regole da scartare e quasi nessuna parsing.

1

Questo thread è vecchio, ma ho deciso di contribuire, perché ho creato un modello molto simile reader system.

EDIT: Alcuni esempi di utilizzo:

 
!defun fact (n) 
    if (zerop n) 
    1 
    * n 
     fact 
     (1- n) 
 
!defun fact !n 
    if !zerop n 
    1 
    !* n !fact !1- n 

Per ulteriori informazioni consulta la home page del progetto.

+1

Questa è effettivamente una risposta solo al collegamento, che qui è disapprovata. Fornisci del contenuto/contesto/campione della "lingua" che il tuo lettore legge. –