Почему Common Lisp нечувствителен к регистру?
Есть ли преимущество в определении функции типа (defun hi () "Hi!")
и иметь возможность вызвать ее с помощью (hi)
или (hi)
или (hi)
или (setf a-number 5)
и иметь возможность доступа к этому номеру с помощью a-number
, a-number
или a-number
?
Если есть такое преимущество, то почему большинство других языков чувствительны к регистру?
Ответы
Ответ 1
Использование регистрозависимых имен в коде в интерактивном сеансе просто более подвержено ошибкам.
Общий Lisp чувствителен к регистру. Просто обычная функция чтения Lisp по умолчанию преобразует все символы без символа в верхний регистр. Это также определено в стандарте Common Lisp. Предустановленные общие символы Lisp также являются внутренними заглавными буквами.
Использование прописных букв было распространено на старых машинах. Помните, что дизайн Common Lisp начался в начале восьмидесятых (1982), и целью была совместимость с более ранним Maclisp и когда было больше типов компьютеров для поддержки (например, так называемых мини-компьютеров и мэйнфреймов). Другие языки программирования, используемые на старых компьютерах, также используют идентификаторы верхнего регистра, такие как COBOL или PL/1.
Также обратите внимание, что Lisp часто используется в интерактивном режиме, так что во время сеанса интерактивного программирования получение права на имена более сложно. Это немного легче, если читатель Lisp использует случай по умолчанию (здесь в верхнем регистре) и преобразует все входные данные в этот случай.
Общие Lisp поддерживает другие режимы считывателя, и вы также можете избежать символов: |This is a Symbol with mixed CASE and spaces|
.
Сегодня большое количество программного обеспечения является либо строчным, либо даже чувствительным к регистру с предпочтительным строчным регистром. Некоторые производители Lisp предоставляют нестандартный вариант Common Lisp, где по умолчанию все символы строчные, а считыватель - в случае сохранения. Но это делает его несовместимым со стандартным Common Lisp, где ожидание состоит в том, что (symbol-name 'cl:defun)
является "DEFUN", а не "defun".
Ответ 2
Для интерактивных сеансов нечувствительность к случаю использовалась по умолчанию, когда был определен стандарт Lisp.
Но что действительно происходит, так это то, что Common Lisp читатель преобразует все символы в верхнее положение перед интернированием и оценкой. Это значение по умолчанию, но вы всегда можете изменить его, если хотите.
Объекты *readtable*
имеют атрибут readtable-case, который определяет, как читатель старается и оценивает прочитанные символы. вы можете setf readtable-case
до :upcase
(по умолчанию), :downcase
, :preserve
, :invert
.
По умолчанию для параметра readtable-case
установлено значение :upcase
, что приводит к преобразованию всех символов в верхний регистр.
Если вам нужна чувствительность к регистру, вы должны сделать
(setf (readtable-case *readtable*) :invert)
=> :invert
На первый взгляд вы можете подумать, что было бы лучше выбрать параметр: preserve, но у него есть небольшая проблема: все символы, определенные стандартом, должны быть увеличены. Таким образом, у вас будет чувствительность к регистру только для символов, определенных вами, и вам придется писать:
* (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
противоположна по умолчанию, преобразуя все в нижний регистр, не давая вам никакой чувствительности к регистру.
Но с :invert
символы, которые вы пишете в исходном коде, например defun
, setf
функцию hi
, преобразуются в верхний регистр, а любой символ в 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
Ответ 3
(Как указывали другие, на самом деле он чувствителен к регистру, но стандартное поведение читателей - это все.)
Что касается преимуществ:
- Вы действительно хотите, чтобы
Hashtable
и Hashtable
называли разные вещи?
- Так как Common Lisp предоставляет разные пространства имен, вам также не нужна капитализация, чтобы разделить имена классов, переменных и функций (среди прочих). Вы можете иметь класс
name
и функцию name
без какой-либо двусмысленности. name
может быть даже именем переменной, кроме этого.
- Как видно из последнего предложения, вы можете использовать буквы в прозе, как и любые другие слова.
Ответ 4
По умолчанию читатель в CL преобразует случай, все экранированные символы переходят в верхний регистр. Вы можете настроить это поведение с помощью readtable-case
. Это связано с тем, что он легко взаимодействует с другими языками, которые следуют тем же соглашениям.