2011-09-11 33 views
14

是否有優勢,定義諸如(defun hi() "Hi!")功能,並能夠通過使用(hi)(HI)(Hi)調用它,或者(setf a-number 5)並能夠訪問使用a-numberA-NUMBER,或A-Number這個數字?爲什麼Common Lisp不區分大小寫?

如果有這樣的優勢,那麼爲什麼大多數其他語言都區分大小寫?

回答

26

在交互式會話中的代碼中使用區分大小寫的名稱更容易出錯。

Common Lisp區分大小寫。 Common Lisp閱讀器功能默認情況下會將所有未轉義的符號字符轉換爲大寫字母。這也在Common Lisp標準中定義。預定義的Common Lisp符號在內部也全部大寫。

在舊機器上使用大寫字母很常見。請記住,Common Lisp的設計始於八十年代早期(1982年),其目標是與早期的Maclisp兼容,以及支持更多類型的計算機(如所謂的迷你計算機和大型機)。在較舊的計算機上使用的其他編程語言也使用大寫標識符,如COBOL或PL/1。

另外請注意,Lisp通常是交互式使用的,所以在交互式編程會話中,名字正確的情況更加困難。當Lisp閱讀器使用默認情況(這裏是大寫)並將所有輸入轉換爲這種情況時,它會稍微容易一些。

Common Lisp支持其他閱讀器模式,您也可以轉義符號:|This is a Symbol with mixed CASE and spaces|

今天很多軟件都是小寫字母,甚至區分大小寫,首選小寫字母。一些Lisp供應商提供了Common Lisp的非標準變體,默認情況下所有符號都是小寫字母,讀者可以保留大小寫。但是這使得它與標準的Common Lisp不兼容,期望(symbol-name 'cl:defun)是「DEFUN」而不是「defun」。

3

默認情況下,CL中的閱讀器是大小寫轉換,所有轉義字符都變成大寫。您可以使用readtable-case自定義此行爲。這是因爲它易於與遵循相同慣例的其他語言進行交互。

+0

嗯, CL界面與哪些語言? – wrongusername

+2

那時?可能是Fortran。請記住,Common Lisp及其前任很早以前就已經在很遠很遠的銀河系中設計過了。 –

+3

這不是特別的Fortran,通常是härdware(Teletype)是大寫字母,而操作系統是使用大寫字母。因此,編程語言也使用大寫字母:PL/1,Cobol,Fortran,Lisp,...在線路編輯模式下通過慢速連接連接的終端上編輯區分大小寫的命令是一種痛苦... –

8

(正如其他人所指出的那樣,它實際上是區分大小寫的,但標準的讀者的行爲是upcase一切。)

至於優點:

  • 你真的想HashtableHashTable要命名不同的東西?
  • 由於Common Lisp提供了不同的名稱空間,因此您也不需要大寫來區分類(class),變量(variable)和函數名稱(除此之外)。你可以有一個類name和一個功能name毫不含糊。最重要的是,Name甚至可以是變量的名稱。
  • 正如在最後一句中所看到的,您可以像使用其他任何詞語一樣將散文中的符號名稱大寫。
+1

好點!但是如果'Hashtable'和'HashTable'應該明確地指向相同的東西,那麼'name'不應該明確指向函數,類或變量? – wrongusername

+3

@wrongusername:這是明確的。當你有一個評估形式'(name foo)',它明確地是一個函數'name';當你有'(defmethod bar((baz name))...)'時,它明確地是一個'name'類(或者更確切地說,類型...);當你看到一個被評估的形式'(quux name)'時,它是一個明確的變量。這與你可以使用「名字」作爲動詞和英語中的名詞而沒有混淆是一樣的。 – Svante

+0

這很有道理。謝謝斯萬特! – wrongusername

12

對於交互式會話,在定義Common Lisp標準時,默認情況下是缺省情況。

但是,真正發生的是,在實習和評估之前,Common Lisp閱讀器將所有符號轉換爲upcase。這是默認設置,但您可以隨時更改它,如果你想。

*readtable*對象具有屬性readtable-case,該屬性控制讀者如何實施和評估讀取的符號。您可以setf readtable-case:upcase(默認),:downcase:preserve,:invert

默認情況下,readtable-case設置爲:upcase,這會導致所有符號轉換爲大寫。

如果你要區分大小寫,你應該做的

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

乍一看,你可能會認爲,這將是更好的選擇:保留選項,但它有一些小問題:所有的符號,如標準所定義的,必須提高。所以,你將不得不由只有你定義的符號區分大小寫,而且必須做的寫:

* (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 

:downcase選項是默認的對立面,將一切downcase,給你不區分大小寫。

但隨着:invert,你在源代碼中寫的符號,像defunsetfhi功能,轉換爲:upcase,並在CamelCase任何符號被保留喜歡它的淵源:

* (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

[This](http://www.cliki.net/case%20sensitivity)澄清了一切。 '(setf(readtable-case * readtable *):invert)'將所有大寫字母都轉換爲小寫字母,所有大寫字母都轉爲小寫字母,因爲所有原始函數默認都是用大寫字母寫的。 – William

相關問題