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

Почему несколько пространств имен?

В чем смысл конструктивного решения иметь отдельные пространства имен для значений и функций в Common Lisp? Каковы аргументы и против?

4b9b3361

Ответ 1

Общий Lisp является в основном потомком от первоначального Lisp 1.5, или, скорее, унификации его расходящихся диалектов. Первоначальный Lisp 1.5 был тем, что в настоящее время называется Lisp -2. Потому что это было в шестидесятые годы, и тот факт, что вы могли передавать функции другим функциям, был довольно странным. Никто даже не подумал бы позволить им использовать одно и то же пространство имен. Почти любой язык, изобретенный сегодня с поддержкой функций более высокого порядка и анонимных функций, выбирает подход с одним пространством имен. Включая Clojure, который в противном случае ближе к Common Lisp, чем к схеме.

Схема, такая как Clojure, первоначально не была расходящимся диалектом от Lisp 1.5, и для их целей имеет смысл.

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

Ответ 3

Хотя в теории может быть много аргументов, я бы поспорил, что он в основном философский по происхождению. Scheme, a Lisp -1, предпочитает элегантность по сравнению с практичностью и выбирает тот же синтаксис define для переменных и функций, что делает одно пространство имен естественным (и поощряет функциональный стиль программирования). Общий Lisp имеет тенденцию отдавать предпочтение практичности и власти над элегантностью и был попыткой построения консенсуса, поэтому, увидев существующее решение с двумя именами, широко принятое и хорошо работающее, приняло его.

Однако на практике это в основном означает три вещи:

  • В Common Lisp (и других Lisp -2's) вам нужно использовать funcall много
  • В схеме (и других Lisp -1) вы должны быть осторожны, чтобы не переопределять необходимые имена функций с переменными; например аргументы функции lst вместо list
  • В Интернете будут аргументы

Это один из основных факторов в том, почему некоторые люди предпочитают один Lisp другому.

Ответ 4

Мне действительно нравится иметь несколько пространств имен (более двух четных); это упрощает работу пользователя и компилятора (реализации):

CL-USER> (defclass test () ())
#<STANDARD-CLASS TEST>
CL-USER> (defun test ())
TEST
CL-USER> (defparameter test 42)
TEST

CL-USER> (describe 'test)
COMMON-LISP-USER::TEST
  [symbol]

TEST names a special variable:
  Value: 42

TEST names a compiled function:
  Lambda-list: ()
  Derived type: (FUNCTION NIL (VALUES NULL &OPTIONAL))
  Source form:
    (LAMBDA ()
      (DECLARE (MUFFLE-CONDITIONS COMPILER-NOTE))
      (PROGN
       (SB-INT:NAMED-LAMBDA TEST
           NIL
         (BLOCK TEST))))

TEST names the standard-class #<STANDARD-CLASS TEST>:
  Direct superclasses: STANDARD-OBJECT
  No subclasses.
  Not yet finalized.
  No direct slots.

; No value

CL-USER> (make-instance 'test)
#<TEST {1005B1D601}>
CL-USER> (test)
NIL
CL-USER> test
42
CL-USER> 

Ответ 5

В дополнение к другим проблемам, упомянутым выше, наличие отдельного пространства имен для функций делает CL негигиеничные макросы гораздо менее вероятными, чтобы укусить пользователя макроса. В CL имя, связанное в точке вызова, которое появляется в расширении макроса, будет иметь определение, используемое в вызывающей точке, а не определение, используемое там, где определяется макрос. Таким образом, в версии CL1 Lisp -1, если макрос расширяется до вызова функции LIST, а LIST определяются как переменная в точке, где был вызван макрос, макрос будет работать неправильно. (Обратите внимание, что gensyms не решают эту проблему, в отличие от обратной задачи, которую они решают.)

Это не происходит в Схеме, потому что по умолчанию макросы Scheme являются гигиеничными: все имена, используемые при расширении макроса, имеют значения, которые они имели там, где определяется макрос, а не где он используется.