Почему Common Lisp нечувствителен к регистру? - PullRequest
14 голосов
/ 11 сентября 2011

Есть ли преимущество в определении функции, такой как (defun hi () "Hi!"), и возможность вызывать ее с помощью (hi) или (HI) или (Hi) или (setf a-number 5) и возможность доступа к этому номеру с помощью a-number, A-NUMBER или A-Number?

Если есть такое преимущество, то почему большинство других языков чувствительны к регистру?

Ответы [ 4 ]

26 голосов
/ 11 сентября 2011

Использование чувствительных к регистру имен в коде в интерактивном сеансе просто более подвержено ошибкам.

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».

13 голосов
/ 19 февраля 2014

Для интерактивных сеансов нечувствительность к регистру использовалась по умолчанию при определении стандарта Common 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
9 голосов
/ 11 сентября 2011

(Как уже отмечали другие, на самом деле он чувствителен к регистру, но стандартное поведение читателя - это все в порядке.)

Что касается преимуществ:

  • Вы действительно хотите, чтобы Hashtable и HashTable называли разные вещи?
  • Поскольку Common Lisp предоставляет разные пространства имен, вам также не нужно использовать заглавные буквы, чтобы отличать имена классов, переменных и функций (среди прочих). Вы можете иметь класс name и функцию name без двусмысленности. Name может быть даже именем переменной, вдобавок к этому.
  • Как видно из последнего предложения, вы можете использовать заглавные буквы в прозе, как и любые другие слова.
3 голосов
/ 11 сентября 2011

По умолчанию читатель в CL конвертирует регистр, все экранированные символы превращаются в прописные.Вы можете настроить это поведение с помощью readtable-case.Это потому, что его легко взаимодействовать с другими языками, которые следуют тем же соглашениям.

...