2011-09-11 14 views
14

C'è un vantaggio per la definizione di una funzione come (defun hi() "Hi!") ed essere in grado di chiamare utilizzando (hi) o (HI) o (Hi), o per (setf a-number 5) ed essere in grado di accedere a tale numero utilizzando a-number, A-NUMBER o A-Number?Perché Common Lisp non è sensibile al maiuscolo/minuscolo?

Se esiste un tale vantaggio, perché la maggior parte delle altre lingue fa distinzione tra maiuscole e minuscole?

risposta

26

L'utilizzo di nomi maiuscole e minuscole nel codice all'interno di una sessione interattiva è solo più soggetto a errori.

Common Lisp fa distinzione tra maiuscole e minuscole. È solo che la funzionalità del lettore Common Lisp di default converte tutti i caratteri senza escape dei simboli in maiuscolo. Questo è anche definito nello standard Common Lisp. Anche i simboli Common Lisp predefiniti sono tutti maiuscoli internamente.

L'utilizzo di lettere maiuscole era comune su macchine vecchie. Ricordate, la progettazione di Common Lisp è iniziata nei primi anni ottanta (1982) e l'obiettivo era la compatibilità con il precedente Maclisp e quando c'erano più tipi di computer da supportare (come i cosiddetti Mini Computers e Mainframes). Altri linguaggi di programmazione utilizzati su computer meno recenti utilizzano anche identificatori maiuscoli, come COBOL o PL/1.

Si noti inoltre che Lisp è stato spesso utilizzato in modo interattivo, pertanto durante una sessione di programmazione interattiva è più difficile trovare il caso dei nomi corretti. È leggermente più semplice quando il lettore Lisp usa un caso predefinito (qui maiuscolo) e converte tutti gli input in questo caso.

Common Lisp supporta altre modalità lettore e può anche sfuggire ai simboli: |This is a Symbol with mixed CASE and spaces|.

Oggi un sacco di software è minuscolo o anche maiuscole/minuscole con caratteri minuscoli preferiti. Alcuni produttori Lisp forniscono una variante non standard di Common Lisp, in cui tutti i simboli di default sono in minuscolo e il lettore preserva il caso. Ma questo lo rende incompatibile con Common Lisp standard, dove l'aspettativa è che (symbol-name 'cl:defun) sia "DEFUN" e non "defun".

3

Per impostazione predefinita, il lettore in CL è la conversione del caso, tutti i caratteri di escape vengono convertiti in maiuscolo. È possibile personalizzare questo comportamento con readtable-case. Questo perché è facile interfacciarsi con altre lingue che seguono le stesse convenzioni.

+0

Hm, con quali linguaggi si interfaccia CL? – wrongusername

+2

All'epoca? Probabilmente Fortran. Ricorda che Common Lisp e i suoi predecessori sono stati progettati molto tempo fa in una galassia molto, molto lontano. –

+3

Non era particolarmente Fortran, era che spesso l'härdware (il Teletype) era maiuscolo e il sistema operativo stava usando le lettere maiuscole. Così i linguaggi di programmazione hanno anche usato lettere maiuscole: PL/1, Cobol, Fortran, Lisp, ... È stato piuttosto doloroso modificare i comandi sensibili al maiuscolo/minuscolo su un terminale collegato tramite connessioni lente in modalità di modifica riga, ... –

8

(Come altri hanno sottolineato, in realtà è tra maiuscole e minuscole, ma il comportamento del lettore standard è a upcase tutto.)

Per quanto riguarda i vantaggi:

  • Vuoi davvero Hashtable e HashTable nominare cose diverse?
  • Poiché Common Lisp offre diversi spazi dei nomi, non è inoltre necessario utilizzare la maiuscola per distinguere i nomi di classi, variabili e funzioni (tra gli altri). È possibile avere una classe name e una funzione name senza ambiguità. Name può anche essere il nome di una variabile, in più.
  • Come visto nell'ultima frase, è possibile utilizzare i nomi dei simboli in lettere maiuscole in prosa come qualsiasi altra parola.
+1

Buoni punti! Ma se 'Hashtable' e' HashTable' dovessero puntare inequivocabilmente alla stessa cosa, il 'name' non dovrebbe essere indirizzato in modo non ambiguo a una funzione, una classe o una variabile? – wrongusername

+3

@wrongusername: non è ambiguo. Quando si ha una forma valutata '(nome pippo)', è inequivocabilmente una funzione 'nome'; quando hai '(defmethod bar ((nome baz) ...)', è un nome di classe 'inequivocabilmente' (o piuttosto tipo ...); quando vedi una forma valutata '(nome di quux)', è senza ambiguità una variabile. È proprio come puoi usare "nome" sia come verbo che come nome in inglese senza confusione. – Svante

+0

Questo ha senso. Grazie Svante! – wrongusername

12

Per le sessioni interattive, l'insensibilità del caso era quella predefinita quando veniva definito lo standard Common Lisp.

Ma, ciò che veramente accade è che il lettore Common Lisp converte tutti i simboli in upcase prima di internarlo e valutarlo. Questo è il valore predefinito, ma puoi sempre modificarlo se lo desideri.

Gli oggetti *readtable* dispongono di un attributo, readtable-case, che controlla il modo in cui il lettore internizza e valuta i simboli letti. È possibile setf readtable-case a :upcase (predefinito), :downcase, :preserve, :invert.

Per impostazione predefinita, readtable-case è impostato su :upcase, che causa la conversione di tutti i simboli in upcase.

Se si desidera la sensibilità caso, si dovrebbe fare

(setf (readtable-case *readtable*) :invert) 
=> :invert 

A prima vista, si potrebbe pensare che sarebbe stato meglio scegliere il: preservare la possibilità, ma ha qualche problema minore: tutti i simboli , come definito dallo standard, deve essere aggiornato. Quindi, si avrebbe caso sensibilità per i simboli definiti dai solo tu, e dovrebbe fare di scrittura:

* (DEFUN hi() "Hi!") 
=> hi 
* (SETF a-number 5) 
=> a-number 
* (HI) 
=> ;error: the stored function is #'HI in the *readtable*, but by 
    ;  calling (HI) you try to acces a function named #'hi(downcase), which 
    ;  gives an error 
* A-NUMBER 
=> ;error: same for the variable 
* (hi) 
=> "Hi!" 
* a-number 
=> 5 

L'opzione :downcase è l'opposto del difetto, la conversione di tutto per downcase originali, senza alcun maiuscole e minuscole.

Ma con :invert, i simboli si scrive nel codice sorgente, come defun, setf la funzione hi, vengono convertiti a upcase, e qualsiasi simbolo in CamelCase si conserva come è originaly:

* (setf (readtable-case *readtable*) :invert) 
=> :invert 
* (defun Hi() "Hi!") 
=> Hi 
* (Hi) 
=> "Hi!" 
* (eq 'Hi 'hi) 
=> nil 
* (eq 'HI 'hi) 
=> nil 
* (eq 'Hi 'Hi) 
=> t 
+1

[Questo] (http://www.cliki.net/case%20sensitivity) chiarisce tutto un po 'di più. '(setf (readtable-case * readtable *): invert)' inverte tutte le lettere maiuscole in minuscolo e tutte maiuscole in minuscole perché tutte le funzioni originali sono scritte in maiuscolo per impostazione predefinita. – William