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

StackOverflow https://stackoverflow.com/questions/1020968

Вопрос

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

Это было полезно?

Решение

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

Википедия ссылается на эту дискуссию :

  

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top