В схеме используется одно пространство имен для всех переменных, независимо от того, связаны ли они с функциями или другими типами значений. Общий Lisp разделяет два, так что идентификатор "привет" может ссылаться на функцию в одном контексте, а строку - на другую.
(Примечание 1: Этот вопрос нуждается в примере выше, не стесняйтесь редактировать его и добавлять к нему или отправлять по электронной почте оригинальному автору, и я сделаю это.)
Однако в некоторых контекстах, таких как передача функций в качестве параметров другим функциям, программист должен явно отличать то, что он вместо функциональной переменной вместо переменной функции указывает спецификацию функции, используя #'
, как в:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
Я всегда считал, что это немного бородавка, но я недавно столкнулся с аргументом, что на самом деле это функция
... важное различие фактически заключается в синтаксисе форм, а не в тип объектов. Не зная ничего о значениях времени выполнения При этом совершенно очевидно, что первый элемент формы функции должна быть функцией. CL принимает этот факт и делает его частью язык, а также макро и специальные формы, которые также могут (и должны) определяется статически. Поэтому мой вопрос: зачем вам имена функций и имена переменных, находящихся в одном и том же пространство имен, когда первичное использование имен функций должно появиться там, где имя переменной редко появлялось бы?
Рассмотрим случай имен классов: почему класс под названием FOO предотвращает использование переменных под названием FOO? Единственный раз, когда я буду ссылаться на класс по имени FOO находится в контекстах, которые ожидают имя класса. Если на редкий случай мне нужно получить объект класса, который связан с имя класса FOO, есть FIND-CLASS.
Этот аргумент имеет для меня некоторый смысл из опыта; в Haskell есть аналогичный случай с именами полей, которые также являются функциями, используемыми для доступа к полям. Это немного неудобно:
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
Это решается небольшим количеством дополнительного синтаксиса, особенно приятным с расширением NamedFieldPuns
:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
Итак, на вопрос, вне согласованности, каковы преимущества и недостатки как для Common Lisp vs. Scheme, так и в общем случае одного пространства имен для всех значений по сравнению с отдельными для функций и нефункциональных значений?