Язык мой — друг мой

pic

О языке программирования AutoLISP как инструменте автоформализации моих профессиональных знаний

На языке искусственного интеллекта программируют те,
кому не хватает интеллекта естественного.
Народная поговорка.

Как известно, персональным компьютером управляют программы. Упрощенно говоря, программа — это последовательность инструкций (команд), понятных компьютеру. Инструкции эти, строчка за строчкой, пишут немного необычные люди, которых все «за глаза» называют программистами. Как правило, это человеческие особи мужского пола (за редким исключением), которые умеют заставить компьютер выполнять свою волю, доходчиво объяснив ему, что от него требуется. Уровень доходчивости, как правило, определяется выбором того языка программирования, который наиболее подходит для решения компьютером именно этой задачи.

Вот уже более полувека идет спор о том, к кому ближе труд программиста — к труду писателя или же к труду ремесленника (только интеллектуального). В самом деле, каждая строчка программы рождается в творческих муках, затем часть или даже все произведение может быть переписано заново. В то же время в результате упорного и кропотливого труда рождается некий программный продукт, который затем может успешно использоваться в различных сферах человеческой деятельности и выступать в качестве средства производства других полезных человеку продуктов. Вообще считается, что изучить основы программирования можно за пару часов, а можно долго пытаться и в результате ничему не научиться.
В настоящее время разработка программного обеспечения для компьютеров производится почти исключительно при помощи языков программирования высокого уровня. Данные языки представляют собой систему мнемонических обозначений, которые понятны человеку и, как правило, преобразуются в последовательность понятных компьютеру машинных команд при помощи специальной программы-транслятора.
За короткий срок развития компьютерных технологий человечество разработало уже несколько десятков языков программирования. Одни были предназначены для применения в очень узкой сфере деятельности и после завершения конкретного проекта больше не использовались. Другие, наоборот, претендовали на универсальность применения и получили большую популярность. Наиболее удачной, на мой взгляд, классификацией языков программирования является классификация по стилю программирования. Она предполагает следующие стили:

1. Неструктурный
2. Структурный
3. Логический
4. Объектно-ориентированный
5. Функциональный.

Неструктурное программирование отличается тем, что допускает использование в явном виде команды безусловного перехода (в большинстве языков GOTO). Типичные представители неструктурных языков — ранние версии Бейсика и Фортрана. Данный стиль вызван особенностями выполнения машиной программы в кодах и унаследован от программ на языке ассемблера (один из языков низкого уровня), поскольку там команда перехода является обязательной. Однако в языках высокого уровня наличие команды перехода влечет за собой массу серьезных недостатков: программа превращается в «спагетти» с бесконечными переходами вверх-вниз, ее очень трудно сопровождать и модифицировать. Фактически неструктурный стиль программирования не позволяет разрабатывать большие проекты. На обычном Бейсике очень удобно быстро написать маленькую учебную программку, но он абсолютно не пригоден для серьезных проектов. Поэтому первоначальное обучение программированию на базе неструктурного языка может привести в дальнейшем к большим трудностям для учащегося при переходе на более современные стили.

pic

Структурный стиль был разработан в середине 60-х — начале 70-х годов. В его основе лежат две идеи:

a) задача разбивается на большое число мелких подзадач, каждая из которых решается своей процедурой или функцией (декомпозиция задачи). При этом проектирование программы идет по принципу сверху вниз: сначала определяются необходимые для решения программы модули, их входы и выходы, а затем уже подробно разрабатываются эти модули. Такой подход вместе с локальными именами переменных позволяет разрабатывать проект силами большого числа программистов.
b) как доказал известный голландский ученый Э. Дейкстра, любой алгоритм можно реализовать, используя лишь три управляющие алгоритмические конструкции: последовательное выполнение, ветвление и цикл (рисунок 1). Данное обстоятельство позволяет при наличии соответствующих операторов исключить из языка команду перехода GOTO.
Принципы структурного программирования были реализованы в языке Алгол, но наибольшую популярность завоевал язык Паскаль, созданный в 1970 швейцарским ученым Н.Виртом. Паскаль получил довольно широкое распространение и может считаться наиболее популярным и сейчас (например, в версии Delphi фирмы Borland).

pic

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

БРАТЬЯ ИМЕЮТ ОДНОГО ОТЦА
ДЖОН — ОТЕЦ ДЖЕКА
МАЙК — БРАТ ДЖЕКА
то система логического программирования сама должна сделать вывод:
ДЖОН — ОТЕЦ МАЙКА.

Хотя работы по логическому программированию ведутся с 50-х годов ХХ века, в настоящее время данное направление несколько потеряло свою актуальность в связи с отсутствием реальных результатов, так как большинство реализованных на принципах логического программирования систем оказалось практически непригодным.

Объектно-ориентированное (ОО) программирование, разработанное в середине 70-х годов Керниганом и Риччи и реализованное в ОО-версиях языков Си и Паскаль, представляет собой отображение объектов реального мира, их свойств (атрибутов) и связей между ними при помощи специальных структур данных. Структурное программирование подразумевает наличие ряда встроенных структур данных: целых, вещественных и строковых переменных, массивов, записей, при помощи которых и производится отображение свойств объектов реального мира. При объектно-ориентированном подходе для объекта создается своя структура данных (класс), содержащая как свойства объекта (характеристики), так и процедуры для управления объектом (методы). Если рассмотреть простейший объект — точку на экране, то она будет иметь как минимум три характеристики (координаты X, Y и цвет) и набор методов (например, «ChangeColor» — поменять цвет, «MoveXY» — переместиться в точку с координатами X,Y и так далее).

pic

Объектно-ориентированный подход является в настоящее время доминирующим при производстве коммерческих программных продуктов, позволяя сократить время разработки и увеличить надежность больших проектов. Однако программы в данном стиле отличаются громоздким синтаксисом; в целом идеология объектно-ориентированного подхода весьма неочевидна, часто воспринимается с трудом (особенно это характерно для языка Си, который и в своем первоначальном виде отличается крайне неудобочитаемым синтаксисом), и переход к его использованию бывает достаточно труден для многих программистов, исповедующих другие стили.
В основе функционального стиля лежит понятие функции как «черного ящика», имеющего набор параметров (аргументов) P на входе и результат обработки функцией этих параметров R на выходе:
f(P)=R
В принципе допускается, что набор параметров может и отсутствовать.
В функциональных языках программирования отсутствуют операторы: все действия, в том числе и управляющие конструкции, выполняются при помощи вызовов функций как элементарных (встроенных), так и определяемых самим программистом при написании программы. Поскольку каждая функция возвращает значение, ее можно подставить в качестве аргумента другой функции, что позволяет записывать сложные выражения в функциональной форме. Одним из первых функциональных языков стал язык Лисп, созданный в конце 50-х годов как язык искусственного интеллекта.
К языкам искусственного интеллекта (сокращенно обозначается AI — artificial intelligence) относят такие языки, которые способны в зависимости от набора исходных данных модифицировать алгоритм работы, то есть «на ходу» менять программу.
Лисп (LISP) был разработан американским ученым Джоном Маккарти в 1957 в Массачусетском технологическом институте. Название языка официально означает LISt Processing (обработка списков), а неофициально — Lots of Idiotic Silly Parentheses («масса идиотских круглых скобок»). Лисп отличается высокой компактностью (ядро интерпретатора занимает не более 10 Кб), функциональным стилем программирования и использованием обратной польской нотации.
Базовым понятием языка Лисп является список. Список — это перечень атомов или списков, отделенных друг от друга пробелами и заключенных в скобки. Как видно из определения, списки могут быть вложенными. Атом в Лиспе — это простой (в отличие от списка) тип данных: число, символьная строка, а также функция.
Пожалуй, главной отличительной особенностью Лиспа является то, что в нем нет различия между текстом программы и обрабатываемыми ею данными. В других языках (например, в Паскале) программа (PROCEDURE, FUNCTION) и данные (VAR, CONST) жестко разделены. В Лиспе же и данные, и текст программы являются списками. Разумеется, список, являющийся программой, включает в себя атомы-функции, которые и вызываются при выполнении программы. То, что с программой можно работать, как с данными, и определяет возможность динамической модификации текста программы, что является свойством языков искусственного интеллекта. Как же отличить список-программу от списка-данных?
В Лиспе по умолчанию любой список является программой и интерпретатор будет пытаться ее выполнить. Если список — не программа, а данные, можно явно отключать его интерпретацию с помощью специальной предназначенной для этого функции.
Из того, что текст программы — тоже список, вытекает необходимость использования специальной системы его записи — обратной польской нотации (названа так по причине изобретения ее польским математиком Яном Лукасевичем). Вызов любой функции в данной нотации записывается как список следующего вида:

(имя_функции a1 a2 … an),
где a1 a2 … an — аргументы функции.

Например, если функция сложения двух чисел имеет имя «+», то операция 2+3 запишется как ( + 2 3 ). В качестве аргументов могут фигурировать другие функции, что позволяет записывать сколь угодно сложные формулы в обратной польской нотации.

Пусть дана функция

pic

В обратной польской записи она приобретает следующий вид:
( * (/ (+ ( * 2 х) 3 ) (- у 1) ) (- у х )).

На первый взгляд такая запись кажется непривычной, но она очень логична и однозначна, что немаловажно для написания правильных программ. К тому же к подобному стилю очень быстро привыкаешь. Кстати, аналогичная нотация использовалась в применяемых раньше программируемых калькуляторах со стеком.
Мое личное знакомство с этим языком произошло еще на заре внедрения персональных компьютеров. В проектном институте, где я работал, на новенькой IBM PC XT была установлена система автоматизированного проектирования AutoCAD — прекрасный графический редактор, позволяющий при помощи своих простых команд отрисовать любую геометрическую фигуру. Изучив эту систему, я вскоре понял, что даже доскональное знание всех команд означает освоение этой системы не более чем на 30% заложенных в нее возможностей. По сути AutoCAD представляет собой мощное средство для создания прикладных систем. И все это благодаря встроенному в него интерпретатору языка AutoLISP (Автолисп) — одного из диалектов языка Лисп. Если вы хорошо представляете свою предметную область и при этом знакомы с Автолиспом, то AutoCAD можно успешно настроить на эффективное решение практически любой инженерной задачи.

pic

Выбор столь экзотического языка в качестве встроенного для столь популярной САПР вызван тем, что список — оптимальный способ представления графической информации. Язык Лисп идеально подошел для системы AutoCAD, «передав» Автолиспу свои очень удобные средства работы с глубокоструктурированной информацией. Кроме того, не последнюю роль сыграли легкость реализации и небольшой размер интерпретатора языка. При этом программы на Автолиспе отличаются чрезвычайно высокой надежностью: за многие годы использования серьезных ошибок в работе интерпретатора выявлено не было.

pic

В следующем номере я попытаюсь подробнее рассказать об особенностях адаптации системы AutoCAD, используя в качестве инструмента язык функционального программирования AutoLISP.

Orphus system