2011-09-11 30 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

相关问题