Функциональное программирования
Стиль разработки программ на Лиспе получил название "функциональное программирование" (ФП). Основные положения этого стиля восприняты многими языками программирования с общей логикой уточнения решаемых задач и обобщения решений на основе выбранных специально базовых конструкций:
Базовые конструкции определяются как строгие функции.При необходимости выполняются преобразования программ, (компиляция, оптимизация, ре-факторинг и т.п.) для улучшения эксплуатационных характеристик, связанных с процессами исполнения программ.Важный критерий качества программирования - полнота системы решений и универсальность реализованных определений для синтаксически управляемой обработки данных функциями высоких порядков (компилятор и т.п.), что существенно повышает надежность проектов для развивающихся постановок задач.Разработка ИС предусматривает выполнение ряда шагов, начальные из которых выполняют роль упрощенных прототипов для реализации последующих, возможно другими, более эффективными, средствами.
Отправляясь от однозначных функций, в Lisp-е обеспечено предельно широкое толкование понятия "значение", объединяющее понятия "структура данных" и "функция":
Ориентируясь на рекурсивные определения функций, введена схема, достаточно удобная для построения формул, задающих функциональные определения. В качестве примера предложен идеальный Лисп (Pure Lisp).Представления функций отображены на множество списков и атомов и определена универсальная функция, по списочному представлению функции и ее аргументов строящая ее результат.Изучено расширение функционального языка, достаточное для стандартного программирования, естественного для привычных задач.
Конструирование функций средствами чистого Лиспа доставляет интеллектуальное удовольствие, оно сродни решению математических головоломок. В этом исключительно мощном языке не только реализованы основные средства, обеспечившие практичность и результативность функционального программирования, но и впервые опробован целый ряд поразительно точных построений, ценных как концептуально, так и методически и конструктивно, понимание и осмысление которых слишком отстает от практики применения.
Понятийно-функциональный потенциал языка Lisp 1.5 в значительной мере унаследован стандартом Common Lisp, но не все идеи получили достойное развитие. Возможно это дело будущего - для нового поколения системных программистов, но это уже другая история.
По мере накопления опыта реализации Лиспа и других языков сформированы обширные библиотеки функций, весьма эффективно поддерживающих обработку основных структур данных - списков, векторов, множеств, хэш-таблиц, а также строк, файлов, директорий, гипертекстов, изображений. Существенно повысилась результативность системных решений в области работы с памятью, компиляцией, манипулирования пакетами функций и классами объектов. Все это доступно в современных системах, таких как GNU Clisp, Python, CMUCL и др., основная проблема при изучении которых – слишком много всего, разбегаются глаза, трудно выбрать первоочередное. Все это превращает любой диалект Лиспа в практичный инструментарий, обладающий интересными перспективами.
Результативность идей Лиспа подтверждена самой историей развития его диалектов и родственных ему языков программирования. (Pure Lisp, Lisp 1.5, Lisp 2, Interlisp, CommonLisp, MicroLisp, MuLisp, Sail, Hope, Miranda, Scheem, ML, GNU Clisp, CLOS, Emacs, Elisp, xLisp, Vlisp, AutoLisp, Haskell, Python, CMUCL). Стандарт Common Lisp в сравнении с Лиспом от МакКарти имеет ряд отличий, несколько влияющих на программотехнику. GNU Clisp, xLisp, CMUCL соответствуют стандарту Common Lisp.
Продуманность и методическая обоснованность первых реализаций Лиспа позволила быстро накопить опыт решения новых задач, подготовить их для прикладного и теоретического программирования. В настоящее время существуют сотни диалектов Lisp-а и языков функционального программирования на базе Lisp-а, ориентированных на разные классы задач и виды технических средств.
Идеи Лиспа выдержали многолетнюю шлифовку и заслужили достойную оценку специалистов и любителей. Универсальность Лиспа достаточна для моделирования любого стиля программирования.
Выразительная сила Лиспа обретает новое дыхание на каждом эволюционном витке развития информационных технологий. Потенциал Лиспа нам еще предстоит раскрыть. Стилистика Лиспа несколько противоречат традиционным подходам к представлению программ. Но это противоречие отступает перед обаянием строгой логики языка. Определение Лисп-систем средствами самого Лиспа дает гибкую основу для развития языка и реализующей его системы программирования. На Лиспе решение задачи выражается в терминах постановки задачи без привлечения реализационных сущностей и интерфейсных эффектов.
Базис Лиспа идеально лаконичен - атомы и простые структуры данных –девять функций и функционалов - обычные функции, которые анализируют, строят и разбирают любые структурные значения (atom, eq, cons, car, cdr,), и специальные функционалы, которые управляют обработкой структур, представляющих вычисляемые выражения (quote, cond, lambda, eval).
Синтаксис Лиспа изысканно прост. Разделитель - пробел, ограничители - круглые скобки. В скобки заключается представление функции с ее аргументами. Все остальное - вариации в зависимости от категории функций, определенности атомов и вычислимости выражений, типов значений и структур данных. Функционалы - это одна из категорий функций, используемая при организации управления вычислениями.
Лисп - язык символьной обработки информации. Методы программирования на Лиспе часто наывают "функциональное программирование". Лисп прочно утвердился как эсперанто для задач искусственного интеллекта. К середине семидесятых годов XX века на Лиспе решались наиболее сложные в практике программирования задачи из области дискретной и вычислительной математики, экспериментального программирования, лингвистики, химии, биологии, медицины и инженерного проектирования. На Лиспе реализована AutoCAD - система автоматизации инженерных расчетов, дизайна и комплектации изделий из доступного конструктива, и Emacs – весьма популярный текстовый редактор в мире UNIX/Linux. Многие созревшие на базе Лиспа системные решения постепенно обрели самостоятельность и выделились в отдельные направления и технологии.
Реализационные находки Лиспа, такие как ссылочная организация памяти, "сборка мусора" - автоматизация повторного использования памяти, частичная компиляция программ с интерпретацией промежуточного кода, длительное хранение атрибутов объектов в период их использования и др., перекочевали из области исследований и экспериментов на базе Лиспа в практику реализации операционных систем и систем программирования.
Приверженцы Лиспа ценят его не только за элегантность, гибкость, но и за способность к точному представлению программистских идей и удобной отладке. В стандартных языках программирования принята императивная организация вычислений по принципу немедленного выполнения каждой очередной команды. Это не всегда обосновано и эффективно. Неимперативные модели управления процессами позволяют прерывать и откладывать процессы, а потом их восстанавливать и запускать или отменять, что обеспечено в Лиспе средствами конструирования функций, блокировки вычислений и их явного выполнения.
История Лиспа пронизана жаркими спорами, притиворечивыми суждениями, яркими достижениями и смелыми изобретениями:
1958 - Первые публикации Джона Мак-Карти о замысле языка символьной обработки.
1962-1964 - Авторские проекты первых Лисп-систем .
1964 - Демонстрация принципиальной решаемости проблем искусственного интеллекта. (Написанная Дж.Вейценбаумом на Лиспе программа-собеседник "Элиза", имитирующая речевое поведение психоаналитика, дала положительный ответ на вопрос о возможности искусственного разума.)
1972-1974 - Разрешение теоретических парадоксов, связанных с бестиповым лямбда-исчислением.
1972-1980 - Стандартизация языка Лисп.
1978 – Появление Лисп-компьютеров.
1965-1990 - Построение специализированных диалектов Лиспа и создание практичных реализаций для широкого спектра весьма различных применений, включая инженерное проектирование и системы математической обработки информации
1992-2002 - Разработка визуальных и сверхэффективных Лисп-систем, таких как CMUCL.
В нашей стране программирование знакомство с языком Лисп состоялось из первых рук.В конце 1968 года Джон Мак-Карти лично познакомил программистов Москвы и Новосибирска с Лиспом, что побудило к реализации отечественных версий языка.
В конце 1968 года Джон Мак-Карти лично познакомил программистов Москвы и Новосибирска с Лиспом, что побудило к реализации отечественных версий языка.
Практичные расширения Лиспа
Средства и методы программирования на Лиспе образуют два слоя. Глубинный слой - локальное программирование, нацеленное на определение:
строгих функций,безотходных структур данных, регулярных отображений, методов оперирования вычислениями.
Внешний слой - моделирование практичных парадигм программирования и механизмов их реализации:
прототипы и макеты программ,интеграция разных стилей и методов программирования,учебное и экспериментальное программирование,проверка новых идей и подходов к организации информационных систем.
Естественно, работа на внешнем слое требует своей терминологии и развития понятий, отражающего расширение класса решаемых задач, повышение уровня общности и организованности решений:
Реальные Лисп-системы обеспечивают полный спектр средств работы с числами с особым вниманием к повышенной точности вычислений и длине представления числа. Средства обработки структур данных обычно позволяют работать с векторами, строками, массивами, хэш-таблицами, деревьями, последовательностями и файлами. Имеется работа с мульти-значениями, удобная при моделировании параллельных вычислений.
Строение Лисп-системы формируется как взаимодействие интерпретатора и компилятора, что позволяет гибко сочетать достоинства того и другого подходов к обработке программ. Для нужд компиляции программа дополняется спецификациями типов данных и декларациями, указывающими направление наследования определений. Имеются средства подготовки и использования встроенной документации и системной информации относительно фактического контекста вычислений. Обстановка функционирования системы регулируется механизмом пакетов, в составе которых хранятся различные варианты определений символов, включаемых в создаваемый комплект.
Так, например, пакет CLOS (Common Lisp Object System) поддерживает ООП в терминах классов, методов, суперклассов, экземпляров и семейств функций, подчиненных механизмам инкапсуляции и наследования с управляемым полиморфизмом.
Вызов Лисп-интерпретатора и/или компилятора.
Без аргументов (опций) выполняется цикл "чтение-вычисление-печать", при котором выражения читаются поочередно из стандартного потока ввода, вычисляются Лисп-интепретатором, и полученные результаты выводятся в стандартный поток вывода. Опция –c специфицирует Лисп-файлы, предназначенные для компиляции в байт-код, который выполняется более эффективно.
Формат вызова Лисп-системы:
clisp [ -h ] [ -m memsize ] [ -M memfile ] [ -L language ] [ -N directory ] [ -q ] [ -I ] [ -i initfile ... ] [ -c [ -l ] lispfile [ -o outputfile ] ... ] [ -p packagename ] [ -x expression ]2)
OPTIONS
-h Показывает формат вызова Лисп-системы
-m memsize Установливает объем памяти. Для современных версий игнорируется.
-M memfile Определяет внутреннее наполнение памяти Лисп-системы. Оно должно быть создано функцией "saveinitmem".
-L language Задает язык сообщений для взаимодействия с пользователем. (английский, немецкий, французский и др.) Влияет на тексты диагностики.
-N directoryУказывает, где искать файлы с текстами сообщений.
-q Ни заставки, ни прощального текста не выдается.
-I вариант диалога в стиле ILISP (популярный интерфейс, принятый в редакторе Emacs)
-i initfile ... Специфицирует инициализирующие файлы, которые будут загружены при запуске системы. Это должны быть исходные или компилированные Лисп-файлы,
-c lispfile ... Компилирует специфицированные Лисп-файлы в байт-код. Компилированные файлы затем загружаются вместо исходных, чтобы повысить эффективность.
-o outputfile Задает файл вывода или директорию для компиляции предшествующего лисп-файла.
-l будет выполняться листинг байткода для компилируемых файлов. Полезно только для целей отладки.
-p packagename При загрузке устанавливает начальное значение переменной *package*
-x expressions Выполняет серию произвольных выражений вместо цикла "read-eval-print". Значения выражений выводятся в стандартный поток вывода. Согласно системным соглашениям выражения должны быть заключены в скобки, а двойным кавычкам и обратным чертам следует предпослать обратную черту.
@optionfile Подставляет содержимое файла как аргумент для запуска Лисп-системы. Каждая строка воспринимается как отдельный аргумент.
При работе с Лисп-системой полезны следующие возможности:
(apropos name) перечисляет символы, включающеие "name"
(exit) or (quit) or (bye) - выход из Лисп-системы
EOF (Ctrl-Z) Покидает текуций "read-eval-print" цикл
Стрелки управления курсором позволяют построчно редактировать и просматривать историю ввода текста программы.
Соглашение об именах файлов:
lisp.exe основной исполнитель
lispinit.mem исходный/начальный образ/состояние памяти
config.lsp конфигурация и настройки
*.lsp исходные тексты на Лиспе
*.fas результат компиляции – байт-код
*.lib библиотечная информация, создаваемая и испоьзуемая компилятором
*.c Си-код, компилированный по исходному Лисп-тексту