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

Какой идиоматический эквивалент C-структур в Lisp?

В языках C-типа особое внимание уделяется структурам/записям и объектам с самого начала и в каждой вводной книге. Затем их полные системы разработаны для управления такими структурами, их взаимоотношениями и наследованием.

В документации Lisp вы обычно можете найти 1-2 страницы о том, как Lisp "также" имеет простую схему defstruct, и обычно это она. Кроме того, вложенность структур никогда не упоминается вообще.

Для кого-то, исходящего из фона C, сначала кажется, что организация разных типов данных иерархически не является предпочтительным методом в Lisp, но помимо CLOS, которая является полномасштабной объектной системой и слишком сложной, если вы просто хотите создавать структуры, и, кроме того, что все вписываются в списки, нет очевидного способа передать ваше знание структуры C.

Что такое идиоматический Lisp способ иерархической организации данных, наиболее напоминающий C-структуры?

-

Я думаю, что итоговый ответ на мой вопрос будет следующим: для начинающих целей обучения, определения структуры и/или plists, хотя "устаревшие функции" могут использоваться, поскольку они наиболее близко напоминают структуры C, но что они были в значительной степени заменены более гибким defclass/CLOS, который используется большинством программ Lisp.

Это был мой первый вопрос о SO, поэтому благодарим всех за ваше время, отвечая на него.

4b9b3361

Ответ 1

Использовать CLOS. Это не сложно.

В противном случае используйте структуры.

Если у вас есть конкретный вопрос, как их использовать, просто спросите.

(defclass point ()
  ((x :type number)
   (y :type number)))

(defclass rectangle ()
  ((p1    :type point)
   (p2    :type point)
   (color :type color)))

В конечном итоге это приводит к таким интерфейсам, как Rectangles в CLIM (Common Lisp Interface Manager).

История

Чтобы немного расширить его: исторически "структуры" использовались в некоторых ситуациях низкого уровня. Структуры имеют одно наследование, а доступ к слотам - "быстрый". Некоторые диалекты Lisp имеют больше структур, чем предлагает Common Lisp. Затем с середины 70-х годов были разработаны различные формы объектно-ориентированных представлений для Lisp. Большая часть представления структурированных объектов перешла от структур к некоторому объектно-ориентированному расширению Lisp. Популярными в 80-е годы были классические системы, такие как Flavors, LOOPS и другие. Также популярны системы на основе рамок или прототипов, такие как KEE Units или Object Lisp. Первый Macintosh Common Lisp использовал Object Lisp для всех своих пользовательских интерфейсов и объектов ввода-вывода. Машина MIT Lisp использовала Flavors в основном везде. Начиная с середины 80-х годов был разработан ANSI CL. Обычная OO-система была разработана специально для Common Lisp: CLOS. Он был основан на Flavors и Loops. В течение этого времени в основном ничего не было сделано для того, чтобы действительно улучшить структуру - помимо разработчиков, которые нашли способы улучшить реализацию и обеспечить неглубокую интеграцию CLOS. Например, структуры не обеспечивают упаковку данных. Если имеется два слота с содержимым в 4 байта, нет возможности проинструктировать Common Lisp для кодирования обоих слотов в одну область с 8-разрядной памятью.

В качестве примера вы можете найти в Lisp Руководство по машинам, глава о структурах (PDF), что у него было гораздо более сложные структуры, чем Common Lisp обеспечивает. Некоторые из них уже присутствовали в Maclisp в 70-х годах: DEFSTRUCT в руководстве Maclisp.

CLOS, Общая Lisp Система объектов

Большинство людей согласятся с тем, что CLOS - хороший дизайн. Иногда это приводит к "большему" коду, главным образом потому, что идентификаторы могут затянуться. Но есть какой-то CLOS-код, такой как тот, что в книге AMOP, который действительно красиво написан и показывает, как он должен использоваться.

Со временем разработчики должны были справиться с проблемой, которую разработчики хотели использовать CLOS, но также хотели иметь "скорость" структур. Это еще больше задача с "полным" CLOS, который включает почти стандартный протокол метаобъектов (MOP) для CLOS. Таким образом, есть некоторые трюки, которые предоставляют разработчики. В течение 80-х годов какое-то программное обеспечение использовало коммутатор, поэтому он мог компилироваться с использованием структур или с использованием CLOS-CLX (примером этого был низкоуровневый Common Lisp X11-интерфейс). Причина: на некоторых компьютерах и реализациях CLOS был намного медленнее, чем структуры. Сегодня было бы необычным предоставить такой компилятор.

Если я посмотрю сегодня на хорошую реализацию Common Lisp, я бы ожидал, что он использует CLOS почти везде. STREAM - это классы CLOS. УСЛОВИЯ - это классы CLOS. Инструментарий GUI использует классы CLOS. Редактор использует CLOS. Он может даже интегрировать иностранные классы (например, классы Objective C) в CLOS.

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

Как упоминалось в некоторых других ответах, в некоторых местах CLOS может не понадобиться.

Общий Lisp может возвращать более одного значения из функции:

(defun calculate-coordinates (ship)
   (move-forward ship)
   (values (ship-x ship)
           (ship-y ship)))

Можно хранить данные в закрытии:

(defun create-distance-function (ship x y)
   (lambda ()
     (point-distance (ship-x ship) (ship-y ship) x y)))

Для конфигурации можно использовать какие-то списки:

(defship ms-germany :initial-x 0 :initial-y 0)

Вы можете поспорить, что я бы применил модель корабля в CLOS.

Урок написания и поддержки программного обеспечения CLOS заключается в том, что его нужно тщательно спроектировать, а CLOS настолько мощна, что с ним можно создавать действительно сложное программное обеспечение - сложность, которая часто не очень хорошая идея. Рефакторинг и упростить! К счастью, для многих задач достаточно базовых средств CLOS: DEFCLASS, DEFMETHOD и MAKE-INSTANCE.

Указатели на введение CLOS

Для начала у Ричарда П. Габриэля есть его документы CLOS для загрузки.

Также смотрите:

Ответ 3

Примеры с defstruct являются короткими и простыми, потому что о них мало что можно сказать. C struct сложны:

  • Управление памятью
  • сложная схема памяти из-за объединений, встроенные вложенные структуры В C, structs также используются для других целей:

  • для доступа к памяти

  • из-за отсутствия полиморфизма или способности передавать значение "любого" типа: идиоматично передавать вокруг void*
  • из-за невозможности иметь другие способы передачи данных; например, в Lisp вы можете передать закрытие, которое имеет необходимые данные.
  • из-за отсутствия предварительных вызовов; некоторые функции принимают свои аргументы внутри структур

В Common Lisp, defstruct примерно эквивалентен Java/С# class: одиночное наследование, фиксированные слоты, могут использоваться как спецификаторы в defmethod (аналогичные методам virtual). Структуры отлично подходят для вложенных структур данных.

Программы

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

Ответ 4

Я думаю, что идиоматический эквивалент структуры C не должен хранить данные в структурах в первую очередь. Я бы сказал, что не менее 50% кода стиля C, который я портировал на Lisp, вместо того, чтобы хранить данные в некоторой сложной структуре, я просто вычисляю то, что я хочу вычислить. C требует, чтобы структуры сохраняли все временно, потому что его выражения настолько слабы.

Если вы являетесь конкретным примером некоторого кода в стиле C, я уверен, что мы могли бы продемонстрировать идиоматический способ его реализации в Lisp.

Кроме того, помните, что Lisp s-exps - это иерархические данные. Выражение if в Lisp, например, представляет собой иерархические данные.

Ответ 5

(defclass point ()
          ( x y z))

(defun distance-from-origin (point)
               (with-slots (x y z)
                   point
                 (sqrt (+ (* x x) (* y y) (* z z)))))

Я думаю, что это то, что я искал, можно найти здесь:

http://cl-cookbook.sourceforge.net/clos-tutorial/index.html у

Ответ 6

Почему бы не использовать хэш-таблицы? Каждый член в структуре может быть ключом в хеш-таблице.