Разработка Lisp-приложений при помощи Cusp - плагина Eclipse

Lisp - это не только искусственный интеллект. Попробовав его, вы станете иначе представлять программирование на Java и C

Lisp - прекрасный язык, который позволяет расширить знание языков программирования, в значительной степени по причине его природы, не предусматривающей определения типов данных. Он также помогает опытным программистам, пишущим на Java™, PHP или C/C++, думать по-новому при разработке приложений. Кроме того, при помощи Lisp можно делать некоторые по-настоящему "крутые" вещи. Узнайте, как разрабатываются Lisp-приложения при помощи Cusp - плагина Eclipse.

Тайлер Андерсон, Независимый автор, Stexar Corp.

Тайлер Андерсон (Tyler Anderson) получил специальность по вычислительной технике в Brigham Young University в 2004 и в настоящее время заканчивает магистратуру. В прошлом он работал программистом баз данных в DPMG.com, а сейчас работает инженером в компании Stexar Corp., расположенной в Beaverton, Ore.



01.04.2008

Cusp - среда разработки Eclipse для Lisp

Cusp - это среда разработки для языка программирования Common Lisp. При помощи Lisp можно разрабатывать все виды приложений, в том числе Web-приложения. Являясь вторым по возрасту из по-прежнему широко применяющихся в настоящее время языков программирования (после Fortran), Lisp известен как первый функциональный язык. Разработка Lisp началась в конце 1950-ых годов и впервые была реализована в рамках MIT Artificial Intelligence (AI) Project в 1958 году. Его сила - это обработка списков (искусственный интеллект и символическая логика). Фактически, Lisp - это аббревиатура от "list processor" (обработка списков), и он, как вы увидите в последующих разделах (в разделе "Ресурсы" приведена историческая информация по Lisp), создавался именно для такой обработки, которая была насущной необходимостью.

Lisp не похож на другие основные языки программирования. Например, в большинстве языков программирования вы представляете операцию умножения так, как делали бы это на бумаге: int times = 5 * 5;.

На Lisp результатом выражения (* 5 5 3) будет число 75. Результатом выражения (MAX 9 8 7 6 20) будет максимально число в списке - 20.

Заметьте, что фраза "первый функциональный язык" здесь очень уместна, поскольку все основывается на функциях. Каждая функция может иметь переменное число параметров. Использование рекурсии и таких Lisp-функций как car и cdr как раз и составляет мощь обработки списков при помощи Lisp.

Учитывая возраст Lisp, не удивительно, что для него существует много сред разработки. Однако, как это свойственно старым языкам программирования, эта инструментальная поддержка является, главным образом, текстовой и не слишком наглядной для начинающих. Таким образом, основная причина попробовать Cusp состоит в том, что он предоставляет интуитивный GUI для начинающих (чтобы изучать Lisp и работать на нем), в отличие от текстового интерфейса типа "попробуй-запомнить-все-эти-команды". Также он обладает великолепными возможностями по управлению проектами, которые присущи инфраструктуре Eclipse GUI.

Прежде чем двинуться дальше, вы должны загрузить самый последний классический пакет Eclipse с Eclipse.org. После этого вы узнаете, как установить и настроить Cusp.


Установка Cusp

Итак, у вас есть заархивированный пакет Eclipse. Разархивируйте его и выполните eclipse.exe.

Чтобы получить последнюю версию Cusp, нажмите Help > Software Updates > Find and Install. Нажмите Search for new features to install. Теперь нажмите кнопку New Remote Site. В name введите Cusp update site, в URL введите http://www.sergeykolos.com/cusp/update, а затем нажмите OK (см. рисунок 1).

Рисунок 1. Ввод информации об удаленном сайте для Cusp
Рисунок 1. Ввод информации удаленного сайта для Cusp

Отметьте флажок рядом с названием добавленного вами нового удаленного сайта и нажмите Finish (см. рисунок 2).

Рисунок 2. Выбор Cusp Eclipse Update Site
Рисунок 2. Выбор Cusp Eclipse Update Site

Вы будете перенаправлены в другое окно, где нужно развернуть Cusp Eclipse Update Site и выбрать Cusp, как показано ниже.

Рисунок 3. Выбор устанавливаемых функциональных возможностей
Рисунок 3. Выбор устанавливаемых функциональных возможностей

Нажмите Next. Прочтите и подтвердите свое согласие с лицензионным соглашением, нажав I accept the terms in the license agreement, а затем нажмите Next. Убедитесь, что выбраны библиотеки, как показано ниже, а затем опять нажмите Next.

Рисунок 4. Выбор дополнительных функциональных возможностей
Рисунок 4. Выбор дополнительных функциональных возможностей

На последней странице отобразятся все функциональные возможности, которые вы собираетесь установить. Нажмите Finish. Плагин и его компоненты будут загружены и установлены. После загрузки вы получите предупреждение о том, что собираетесь установить неподписанную функцию. Нажмите Install all. В конце установки вы получите запрос на перезапуск Eclipse; нажмите Yes.

Вы установили Cusp - плагин Eclipse. Теперь нужно настроить Lisp-проект.


Настройка Lisp-проекта

Прежде чем начать Lisp-разработку, нужно создать новый Lisp-проект. Это можно сделать, перейдя в File > New > Project. Разверните папку Lisp, нажмите Lisp Project, а затем Next. Введите название нового проекта, my_new_lisp_project, как показано ниже, а затем нажмите Finish.

Рисунок 5. Задание названия нового Lisp-проекта
Рисунок 5. Задание названия нового Lisp-проекта

После нажатия Finish создастся новый проект, и откроется Lisp-перспектива, как показано ниже.

Рисунок 6. Lisp-перспектива
Рисунок 6. Lisp-перспектива

Рассмотрим перспективу Lisp. В окне Lisp Navigator показан открытый проект и связанные с ним файлы. В окне Outline показана структура открытого в настоящее время файла. Правое верхнее окно, в котором открыт файл main.lisp, - это окно Lisp-разработки. Правое нижнее окно, REPL, - это командная строка Lisp-интерпретатора, где можно выполнять Lisp-команды.

Если вы закроете Eclipse, а затем снова откроете его, необходимо загрузить .asd-файл вашего проекта, как показано ниже.

Рисунок 7. Загрузка ASD-файла
Рисунок 7. Загрузка ASD-файла

Вы должны щелкнуть правой кнопкой мыши на файле my_new_lisp_project.asd в папке my_new_lisp_project и выбрать Load asd. Таким образом, ваш Lisp-проект будет скомпилирован в окне REPL, и вы сможете вводить новые Lisp-команды.

Теперь можно начинать Lisp-разработку при помощи Cusp.


Lisp-разработка при помощи Cusp

Прежде всего, задайте простую пользовательскую функцию и протестируйте ее. Откройте файл main.lisp и добавьте в него команду defun (задать функцию):

...
(defun first_howdy_function ()
  "howdy ho")

Сохраните файл. Чтобы экспортировать функцию из пакета, в defpackage.lisp введите следующий код:

...
   ;; Exported symbols go here
  first_howdy_function
   ))

Теперь функцию можно использовать извне пакета. Чтобы протестировать вашу новую функцию, введите в нижней части окна REPL следующее: (my_new_lisp_project:first_howdy_function).

Обратите внимание, что для области, в которой вы находитесь, это то же самое, что ввести (my_new_lisp_project::first_howdy_function). Такую команду вы должны были бы ввести, если бы не экспортировали функцию в defpackage.lisp.

Нажмите Send и проверьте выходную информацию. После ввода любой из приведенных выше команд она должна быть следующей:

COMMON-LISP-USER>
(my_new_lisp_project:first_howdy_function)

"howdy ho"

Теперь у вас есть ваша первая Lisp-функция Howdy.

Опробуйте функцию echo, введя:

...
(defun first_echo_function (echoval)
  echoval)

Как и в случае с предыдущей функцией, экспортируйте ее в defpackage.lisp. Чтобы протестировать функцию first_echo_function, в нижней части окна REPL введите: (my_new_lisp_project:first_echo_function '("howd" "y h" "o")). Обратите внимание, что часть '("howd" "y h" "o") данной команды - это синтаксис для задания списка. Одиночная кавычка, предшествующая круглым скобкам, говорит о том, что в скобках заданы элементы списка. Выходная информация показана ниже:

COMMON-LISP-USER>
(my_new_lisp_project:first_echo_function '("howd" "y h" "o"))

("howd" "y h" "o")

Далее вы создадите метод для индивидуальной обработки каждого элемента списка, в чем и состоит истинная сила Lisp. Задайте его следующим образом:

(defmethod concat2 ((str1 string) (str2 string))
  (concatenate 'string str1 str2))

Обратите внимание, что этот метод, фактически, задает строковый тип. До настоящего времени вы использовали Lisp в значительной степени как язык, не предусматривающий определения типов данных. Хотя двойные кавычки неявно указывают, что данные являются строковыми, приведенный выше метод явно задает ввод и вывод функции concat2 как строки. Метод также использует встроенную функцию concatenate (конкатенация), чтобы соединить две строки и возвратить их как одну строку.

Чтобы протестировать concat2, экспортируйте его, а затем введите (my_new_lisp_project:concat2 "howd" "y ho"). Выходная информация будет следующей:

Листинг 7. Вывод двух соединенных строк
COMMON-LISP-USER>
(my_new_lisp_project:concat2 "howd" "y ho")

"howdy ho"

Строки "howd" и "y ho" превратились в "howdy ho". Сейчас вы создадите более обобщенную функцию конкатенации, используя две знаменитые Lisp-функции: car и cdr.

Листинг 1. Соединение трех элементов в списке
(defun concat3 (args_list)
  (concat2 (car args_list)
           (concat2 (car (cdr args_list))
                    (car (cdr (cdr args_list))))))

Обратите внимание, что в данной функции используется функция concat2, но только со списком ее входных параметров. Каждый элемент конкатенации извлекается из args_list. Функция car возвращает первый элемент списка. Функция cdr возвращает список без первого элемента. Таким образом, вы получаете первый элемент списка, просто вызывая функцию car по списку. Чтобы получить второй элемент, нужно вызвать функцию cdr по списку, а затем функцию car по этому новому списку. Третий элемент можно получить, дважды вызвав функцию cdr по списку, а затем функцию car по окончательному списку.

Выходная информация приведенной выше функции (после ее экспортирования) будет выглядеть так:

COMMON-LISP-USER>
(my_new_lisp_project:concat3 '("howd" "y h" "o"))

"howdy ho"

Вот и все. Три строки были корректно соединены во фразу "howdy ho". Далее вы создадите рекурсивную функцию.


Рекурсия в Lisp

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

Начнем с создания рекурсивной функции concat.

Листинг 2. Рекурсивная конкатенация (неограниченное количество параметров)
1   (defun concat_recursive (args_list)
2     (if (equal (cdr args_list) nil)
3         (car args_list)
4         (concat2 (car args_list)
5                  (concat_recursive (cdr args_list)))))

Рекурсия может быть сложной для понимания, поэтому давайте подробно рассмотрим конкретный случай:

  • Представьте себе, что в вышеуказанную функцию передается произвольный список параметров.
  • Если в списке только один элемент ((cdr args_list) в строке 2 возвращает нуль), возвращается единственный элемент ((car args_list) в строке 3).
  • Если в списке больше одного элемента ((cdr args_list) в строке 2 не возвращает нуль), возвращается результат конкатенации (используется concat2) первого элемента списка (см. строку 4) и результата рекурсивного вызова concat_recursive, использующей в качестве параметров результат (cdr args_list) (см. строку 5).

Давайте пошагово рассмотрим результаты при передаче списка параметров '("ho" "wd" "y" " h" "o"):

  • Когда строка 2 выполняется в первый раз, результатом if является false, и concat2 вызывается с "ho" и (concat_recursive '("wd" "y" " h" "o")).
  • Когда строка 2 выполняется во второй раз, результатом if опять является false, и concat2 вызывается с "wd" и (concat_recursive '("y" " h" "o")).
  • Когда строка 2 выполняется в третий раз, результатом if опять является false, и concat2 вызывается с "y" и (concat_recursive '(" h" "o")).
  • Когда строка 2 выполняется в четвертый раз, результатом if опять является false, и concat2 вызывается с " h" and (concat_recursive '("o")).
  • На пятый раз наступает магический момент, когда рекурсия заканчивается. Это происходит потому, что результатом if теперь является true, и возвращается просто "o". Распишем рекурсию:
    • Четвертый вызов: соединяются и возвращаются " h" и "o".
    • Третий вызов: соединяются и возвращаются "y" и " ho".
    • Второй вызов: соединяются и возвращаются "wd" и "y ho".
    • Первый вызов: соединяются и возвращаются "ho" и "wdy ho" как окончательный результат.

В конечном итоге вы получили "howdy ho", что показано ниже:

COMMON-LISP-USER>
(my_new_lisp_project:concat_recursive '("ho" "wd" "y" " h" "o"))

"howdy ho"

Ваш арсенал Cusp-разработчика пополнен рекурсией. Далее займемся отладкой.


Отладка при помощи Cusp

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

Введите следующую команду: (my_new_lisp_project:concat_recursive '("ho" "wd" "y" 55 " h" "o")). Обратите внимание, что число 55 не заключено в двойные кавычки, а значит не является строкой, и это приведет к запуску отладчика, как показано ниже.

Рисунок 8. Запуск отладчика
Рисунок 8. Запуск отладчика

Заметьте, что главная ошибка, вызвавшая отладчик, состоит в том, что concat2 не может быть вызвана по списку (55 " ho"). Также обратите внимание, что " h" и "o" уже были соединены до возникновения ошибки.

В окне отладчика есть ==Backtrace== (обратная трассировка), показанная на рисунке 8. Каждая строка ниже (в данном случае 0-19) дает детальную трассировку с момента нажатия Send и до возникновения ошибки. Здесь вы можете проследить рекурсию, дошедшую до числа 55, что и вызвало ошибку.

Что дальше? У вас есть три варианта выйти из отладчика и изменить входные данные. Можно прервать команду и вернуться в обычное окно REPL. Можно закрыть соединение (если в процессе тестирования выбирается этот вариант, потребуется перезагрузка Eclipse, чтобы перезапустить Lisp-процессор). Также можно просто прервать работу отладчика и вернуться в обычное окно REPL. Наилучший вариант - прервать работу отладчика, следствием чего всегда будет прекращение выполнения команды и возвращение в обычное окно REPL.

Вот и все. Вы реализовали рекурсивную функцию в Lisp.


Резюме

Вы успешно завершили Lisp-разработку при помощи Cusp - плагина Eclipse. Теперь вы должны знать, в чем состоит мощь Lisp. При помощи простых рекурсивных операторов можно легко обрабатывать списки символов и данных. Cusp дополняет возможности Lisp, предоставляя встроенный Cusp-отладчик, солидный GUI с возможностями управления проектами, интерактивный Lisp-редактор и интерфейс командной строки для Lisp-процессора, где можно вводить команды и тестировать код. Чтобы получить больше информации, просмотрите раздел "Ресурсы".


Загрузка

ОписаниеИмяРазмер
Пример кода для статьи о Cuspos-eclipse-lispcusp.code.zip28KB

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=299059
ArticleTitle=Разработка Lisp-приложений при помощи Cusp - плагина Eclipse
publish-date=04012008