Язык Common LISP, эквивалентный перечислениям C

Во время выполнения дженерики не являются reified . Это означает, что информация отсутствует во время выполнения.

Добавление дженериков в Java при сохранении обратной совместимости было де-силовым (вы можете ознакомиться с оригинальной статьей: Создание будущего безопасный для прошлого: добавление универсальности к языку программирования Java ).

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

18
задан pupeno 15 May 2009 в 11:01
поделиться

3 ответа

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

Поэтому, где в C Вы могли бы записать:

enum {
   apple,
   orange,
   banana,
};

В Lisp можно просто использовать 'apple, 'orange и 'banana непосредственно.

при необходимости в перечислимом тип , затем можно определить один с [1 110] deftype :

(deftype fruit () '(member apple orange banana))

и затем можно использовать тип fruit в declare, typep, typecase и так далее, , и можно записать родовые функции, которые специализируются на том типе .

21
ответ дан 30 November 2019 в 06:59
поделиться

Например, Вы хотите назвать размеры шрифта:

(defconstant +large+ 3)
(defconstant +medium+ 2)
(defconstant +small+ 1)

Вы могли записать макрос для создания этого короче.

Выше постоянных определений обычно пишутся ТОЛЬКО, когда эти числа должны быть переданы некоторому внешнему коду не-Lisp.

Иначе можно было бы просто использовать символы ключевого слова:: большой: носитель и: маленький.

можно протестировать их с EQ и всем, что использует некоторый тест для равенства.

(let ((size :medium))
  (ecase size
    (:small ...)
    (:medium ...)
    (:large ...)))

можно также записать методы для него:

(defmethod draw-string (message x y (size (eql :large))) ...)

, Как упомянуто Вы могли определить тип набора:

(deftype size () '(member :small :medium :large))

Тогда можно проверить, имеет ли что-то любой тех:

(let ((my-size :medium))
  (check-type my-size size))

Выше сигнализировал бы об ошибке, если мой-размер не является одним из: маленький: носитель или: большой.

можно также использовать тип в форме defclass:

(defclass vehicle ()
   ((width :type size :initarg :width)))

Теперь Вы создали бы объекты как здесь:

(make-instance 'vehicle :width :large)

Некоторые реализации языка Common LISP проверят при установке слота на некоторое недопустимое значение.

, Если Вы теперь создаете объекты механизма класса, слоты будут одним из: большой: носитель или: маленький. При рассмотрении объекта в отладчике инспекторе или некотором другом инструменте, Вы будете видеть символьные имена а не 1, 2 или 3 (или безотносительно значений, которые Вы обычно использовали бы).

Это - часть стиля Lisp: используйте символьные имена, если это возможно. Используйте символы с числовыми значениями только в интерфейсном коде к внешним функциям (как вызов внешнего кода C, который использует перечисления).

15
ответ дан 30 November 2019 в 06:59
поделиться

Перечисления избыточны для Lisp, при этом причина состоит в том, что все символы являются своими собственными идентификационными данными, таким образом, можно просто использовать их, например:

[dsm@localhost:~]$ clisp -q
[1]> (setf x 'some) ;'
SOME
[2]> (eq x 'some) ;'
T
[3]>
6
ответ дан 30 November 2019 в 06:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: