Подтвердить что ты не робот

Отдельные пространства имен для функций и переменных в Common Lisp по сравнению с схемой

В схеме используется одно пространство имен для всех переменных, независимо от того, связаны ли они с функциями или другими типами значений. Общий 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, так и в общем случае одного пространства имен для всех значений по сравнению с отдельными для функций и нефункциональных значений?

4b9b3361

Ответ 1

Два разных подхода имеют имена: Lisp -1 и Lisp -2. A Lisp -1 имеет одно пространство имен для обеих переменных и функций (как в схеме), а Lisp -2 имеет отдельные пространства имен для переменных и функций (как в Common Lisp). Я упоминаю об этом, потому что вы можете не знать о терминологии, поскольку вы не ссылались на нее в своем вопросе.

Wikipedia относится к этой дискуссии:

Является ли отдельным пространством имен для функций преимуществом, является источником разногласий в сообществе Lisp. Обычно это называется дискуссиями Lisp -1 и Lisp -2. Lisp -1 относится к модели схемы, а Lisp -2 относится к общей модели Lisp. Эти имена были придуманы в статье 1988 года Ричардом П. Габриэлем и Кентом Питманом, в которой широко сравниваются два подхода.

В этой статье рассматривается статья Габриэля и Питмана под названием Технические вопросы разделения в ячейках функций и ячейках значений.

Ответ 2

Собственно, как указано в статье Ричарда Габриэля и Кента Питмана, дискуссия о Lisp -5 против Lisp - 6, так как там уже есть несколько других пространств имен, в документе упоминаются имена типов, имена тегов, имена блоков и имена деклараций. edit: это кажется неправильным, как указывает Райнер в комментарии: схема действительно выглядит как Lisp -1. Однако эта ошибка в значительной степени не затронута этой ошибкой.

Указывает ли символ что-то, что нужно выполнить, или что-то, о чем следует ссылаться, всегда ясно из контекста. Бросание функций и переменных в одно и то же пространство имен в основном ограничено: программист не может использовать одно и то же имя для вещи и действия. Что означает Lisp -5, так это то, что некоторые синтаксические накладные расходы для ссылки на что-то из другого пространства имен, чем то, что подразумевается в текущем контексте, избегают. edit: это не вся картина, просто поверхность.

Я знаю, что Lisp -5 сторонников, как факт, что функции являются данными, и что это выражается в ядре языка. Мне нравится, что я могу назвать список "список" и автомобиль "автомобиль", не запутывая мой компилятор, и функции в любом случае являются принципиально особым видом данных. edit: это мой главный момент: отдельные пространства имен вообще не являются бородавкой.

Мне также понравился о чем Паскаль Констанца говорил об этом.

Ответ 3

Я встречал аналогичное различие в Python (унифицированное пространство имен) против Ruby (различные пространства имен для методов против не-методов). В этом контексте я предпочитаю подход Python - например, с этим подходом, если я хочу составить список вещей, некоторые из которых являются функциями, а другие нет, мне не нужно ничего менять с их именами, в зависимости от их "функциональности", например. Подобные соображения применимы ко всем случаям, в которых функциональные объекты должны быть объединены, а не вызваны (аргументы и возвращаемые значения из функций более высокого порядка и т.д. И т.д.).

Также могут быть вызваны не-функции (если их классы определяют __call__, в случае Python - частный случай "перегрузки оператора" ), так что "контекстуальное различие" также не обязательно является ясным.

Однако мой опыт "lisp -oid" в основном связан с Scheme, а не с Common Lisp, поэтому я могу быть подсознательно предвзято знакомством с равномерным пространством имен, которое в конечном итоге происходит из этого опыта.

Ответ 4

Самый большой недостаток, который я вижу, по крайней мере для Common Lisp, является понятным. Мы все можем согласиться с тем, что он использует разные пространства имен для переменных и функций, но сколько у него есть? В PAIP Норвиг показал, что у него есть "по крайней мере семь" пространств имен.

Когда одна из классических книг, написанная очень уважаемым программистом, не может даже сказать наверняка в опубликованной книге, я думаю, что есть проблема. У меня нет проблем с несколькими пространствами имен, но я хочу, чтобы язык был, по крайней мере, достаточно простым, чтобы кто-то мог полностью понять этот аспект.

Мне удобно использовать один и тот же символ для переменной и для функции, но в более неясных областях я прибегаю к использованию разных имен из страха (сталкивающиеся пространства имен могут быть очень трудными для отладки!), и это действительно должно никогда не будет.

Ответ 5

Имя функции в Схеме - это просто переменная с функцией как ее значение. Я делаю (define x (y) (z y)) или (let ((x (lambda (y) (z y)))), я определяю функцию, которую я могу вызвать. Таким образом, идея о том, что "имя переменной редко хотела бы появиться там", является довольно сообразительной, насколько это касается Схемы.

Схема - это характерно функциональный язык, поэтому рассмотрение функций как данных является одним из его принципов. Наличие функций своего типа, которые хранятся, как и все другие данные, является способом реализации идеи.

Ответ 6

Есть хорошие вещи для обоих подходов. Тем не менее, я считаю, что, когда это имеет значение, я предпочитаю иметь как функцию LIST, так и переменную LIST, чем неправильно писать одно из них.