Точка использования внедрения зависимостей (и в этом отношении контейнера IoC) в LISP - PullRequest
4 голосов
/ 06 декабря 2011

Я прочитал эссе ESR под названием "Как стать хакером?" Несколько лет назад (ссылку можно найти в моем профиле) и Эрик предложил изучить LISP. Ну, я довольно давно изучаю LISP, и он мне так нравится, что я решил написать веб-приложение, используя его.

Поскольку я некоторое время пользуюсь Spring, я думаю, что было бы неплохо написать несвязанные компоненты и склеить их вместе с помощью контейнера IoC и внедрения зависимостей. Я провел мощный поиск в Google, и оказалось, что в LISP такой идеи нет. Я что-то пропустил? Есть ли хорошая реализация этой концепции в LISP или нет смысла использовать ее по какой-то причине, которая мне еще не ясна?

Ответы [ 2 ]

19 голосов
/ 06 декабря 2011

«Инверсия контроля» широко используется в Лиспе.Это совершенно просто, поскольку функции и замыкания являются объектами первого класса.

Внедрение зависимостей тривиально.Классы и функции могут быть сконфигурированы с помощью символов и классов первого класса.

Обычно вам не требуется «каркас» для IoC или DI в Common Lisp, так как множество функций для настройки и параметризации приложений и библиотеквстроенный.

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

В таком языке, как Common Lisp, функции и классы являются объектами первого класса,Кроме того, для развязки с помощью позднего связывания вы можете использовать вместо символов символы.Система объектов Common Lisp знает мета-классы и символы как имена для классов.Даже общие функции и методы являются объектами и имеют мета-классы.

Если concurrent-secure-server - это класс, а default-response - это функция, вы можете сделать, например:

(make-instance 'web-services
               :server-class 'concurrent-secure-server
               :default-response-function 'default-reponse)

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

В качестве альтернативы:

(make-instance 'web-services
               :server-class (find-class 'concurrent-secure-server)
               :default-response-function #'default-reponse)

В вышеупомянутом случае мы передаем объект класса и объект функции.

В программных модулях Common Lisp могут быть глобальные переменные, которые вы можете установить с правильной информацией:

 (defvar *default-server-class* 'concurrent-secure-server)

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

(defclass server-object ()
  ((default-response-function
      :initarg :default-response-function
      :initform *server-default-response-function*)))

(defvar *my-server*
   (make-instance 'server-object
                  :default-response-function 'my-default-response-function))

Вы даже можете создавать объекты, а затем изменять их класс на этапе настройки.Common Lisp Object System позволяет вам изменять классы и обновлять существующие объекты.

Если вы создаете экземпляр, вы можете быть настолько гибкими, насколько захотите:

  • вы можетепередавая класс
  • , вы можете передавать аргументы

Примерно так:

(let ((my-class 'foo-class)
      (my-args  `(:response-function ',*some-reponse-function)))
  (apply #'make-instance my-class my-args))

Иногда вы видите библиотеки Lisp, которые вычисляют такие списки аргументов во время выполнения,

Еще одна вещь, где вы можете конфигурировать приложения на Лиспе во время выполнения, - это общие функции.Общие функции позволяют: before,: after и: around методы - они даже позволяют использовать ваши собственные схемы вызовов.Таким образом, используя ваши собственные классы, наследуемые от других классов и классов смешивания, универсальная функция переконфигурируется.Это похоже на то, что у вас есть встроенные базовые механизмы Аспектно-ориентированного программирования.

Для людей, интересующихся этими более продвинутыми объектно-ориентированными концепциями, есть некоторая литература Xerox PARC, где эти проблемы были исследованы при CLOSбыл создан.Тогда он назывался «Открытая реализация»:

http://www2.parc.com/csl/groups/sda/publications.shtml

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

Одна вещь, которая вам не нужна: XML.Common Lisp - это собственный язык конфигурации.Написание расширений для более легкой настройки может быть сделано, например, с помощью макросов.Загрузка этих конфигураций может быть легко выполнена с помощью LOAD.

3 голосов
/ 06 декабря 2011

На самом деле IoC - это принцип построения большинства веб-фреймворков, не только в Java или Lisp. Что касается DI, как заметил Раммарен, это неявный паттерн в динамическом языке, таком как Lisp. Вы можете убедиться в этом сами, если сравнить приложения Hello World в Spring и Restas (одна из хорошо поддерживаемых веб-платформ CL). Вы увидите, что есть тот же шаблон, за исключением отсутствия необходимости в необычном типе / классе / интерфейсе объявлений в Лиспе.

...