Языки программирования. Прошлое и будущее. С.Бобровский (1012869), страница 7
Текст из файла (страница 7)
Не секрет, что в России наиболее популярными языками программирования являются С, C++ и Паскаль. И нередко ассемблер. Это довольно
сильно отличает нашу страну от остального мира, где программы для Windows часто пишут на языке Visual Basic.
Но существует еще очень много других языков, как известных, так и незаслуженно забытых. Причем для ряда задач их использование дает •весьма ощутимые преимущества, позволяя отвлечься от семантики языка и деталей реализации и полностью сконцентрироваться на поставленной задаче. При этом обеспечиваются не только высокое качество, надежность и эффективность получаемых программ, но и наглядность и быстрота разработки.
Одним из таких языков является LISP (LISt Processing — обработка списков). Его придумал в 1956 году профессор Массачусетского технологического института Джон Маккарти для занятий со студенческой научной группой. Язык предназначался для анализа и разбора английских фраз в рамках проекта по искусственному интеллекту «Принимающий советы». Сначала это были версии для первых компьютеров IBM и DEC. Более или менее законченный вариант — LISP 1.5 — появился в 1965 году.
Лисп, как следует из его названия, предназначен для обработки списков, состоящих из атомов — абстрактных элементов, которые представляют собой формально неограниченные по длине цепочки символов. Они могут трактоваться как строки в более привычном понимании, числа или представлять собой некие логические структуры с вложенными на неограниченную глубину подсписками в виде иерархических деревьев. Например, любая фраза является для Лисп типичным списком. По требованиям языка список должен быть заключен в скобки. Для обработки списков используется функциональная модель, базирующаяся на теории лямбда-исчисления Черча. Фактически, программа на Лиспе представляет собой набор лямбда-функций, при этом работа со списками осуществляется с помощью базового набора примитивов типа CAR/CDR (взять первый элемент списка, который сам может быть списком/получить список без первого элемента). Таких примитивов в минимальном наборе всего 13 штук. С их помощью и, главное, благодаря рекурсивной системе обработки информации, Лисп позволяет очень компактно описывать функции, для реализации которых на других языках программирования потребовались бы сотни и тысячи строчек кода.
Как оказалось, на Лиспе очень удачно описываются и программируются задачи, в которых требуется обработка абстрактной структурной информации. Это такие задачи, как автоматическое доказательство теорем, понимание естественного языка и окружающего мира, логические исчисления, написание компиляторов. Этот язык оказался столь мощным, что сегодня значительное число интеллектуальных систем четвертого поколения используют его диалекты в качестве основного языка разработки.
После первых впечатляющих успехов актуальной стала задача эффективной реализации языка. Сначала все Лисп-системы были интерпретируемыми, что позволяло достичь определенной гибкости, но сильно замедляло сам процесс работы программы. Автор Лиспа опубликовал в 1965 году свою книгу «LISP 1.5 Programmer's Manual », в которой описал не только язык, но и структуру так называемой виртуальной Лисп-машины, некоей абстрактной схемы функционирования Лисп-системы, а также формальное определение структуры компилятора и интерпретатора. Этот труд стал образцом классического описания языка программирования и его окружения, и на него ссылаются вплоть до сегодняшнего дня. Удивительная ясность и простота Лиспа в сочетании с его мощностью и оригинальной идеологией сделала его не просто языком программирования, а своего рода способом формального описания алгоритмов. Кроме того, многие идеи, заложенные в языке Лисп (например, «сборка мусора», или оптимизация памяти, освобождение ее от «висячих ссылок»), актуальны и по сей день.
Примерно к этому времени относится и первое совершенное в отношении Лиспа преступление, лишившее его основного преимущества перед другими языками — прозрачности структуры программы. Кто-то, я не знаю точно, может быть, это был сам Великий (Джон Маккарти), ввел в программу примитив PROG, позволяющий писать операторы последовательно, один за другим, как в Фортране или Алголе, и, что самое страшное, добавил оператор GO (goto), без которого примитив PROG, очевидно, был лишен всякого смысла. С этого момента развитие Лиспа пошло под откос.
В начале 70-х годов Лисп-машина была реализована в ряде компьютеров таких фирм, как Xerox и Texas Instruments. Для повышения эффективности функционирования она была «воплощена в железе» (как сказали бы сейчас, «система была зашита в ПЗУ»).
В конце 70-х годов бурно расцвела теория искусственного интеллекта и стали актуальными средства для реализации ее идей. Язык Лисп пережил второе рождение. Было создано множество вариантов языка практически для всех платформ и операционных систем. Именно тогда появились два диалекта, которые стали основоположниками сегодняшних стандартов. Это, прежде всего, Scheme Lisp, который точнее всего унаследовал чистоту оригинальной идеологии своего родоначальника. Пройдя глубокую математическую переработку, эта версия, по-прежнему ограничиваясь небольшим числом базовых примитивов (полное
описание языка занимает всего 50 страниц), позволила сосредоточиться на ключевых деталях при решении ряда математических задач, требующих формального описательного аппарата. Например, оригинальной и многообещающей оказалась идея engines — параллельных процессов. Поэтому в большинстве научных групп используется именно эта версия Лиспа.
Второй диалект, Common Lisp (CL), наоборот, отличался очень большой библиотекой разнообразных функций, чуть ли не превосходящих по количеству аналогичные библиотеки Фортрана(!). Его, конечно, значительно удобнее использовать для реализации конкретных проектов, требующих, помимо простого анализа списочных структур, еще и больших объемов вычислительной работы и организации хорошего графического интерфейса. Описание этого диалекта занимает уже около 1300 страниц, в него введено довольно много возможностей обычных процедурных языков типа Си, например, строгая типизация, которая в оригинальном Лиспе отсутствовала вообще.
Язык CL сильно отличается от языка LISP 1.5 60-х годов. Хотя он и включает в себя все базовые возможности, в реальных проектах обычно используется не рекурсивная, а линейная структура программы, более соответствующая человеческой психологии и более близкая к привычным языкам. Однако из-за отказа от оригинальной идеологии, требовавшей очень четко формализовать задачу в почти математических терминах, сразу возникли проблемы, характерные для обычных задач проектирования и реализации крупных проектов.
После активного распространения Unix в 80-х годах получила широкое распространение версия Portable Standard Lisp, реализованная на большинстве платформ, и, наконец, Common Lisp стал фактическим стандартом. А 8 декабря 1994 года в Американском институте национальных стандартов было зарегистрировано официальное описание этого языка ANSI X3.226:1994 (X3J13), которое действует и сегодня.
Всплеск интереса к объектно-ориентированному программированию не обошел и Лисп. В него были добавлены понятия объекта, метода, наследования и вскоре появился объектный стандарт Common Lisp Object System (CLOS). При этом изобретатели стандарта не понимали или не хотели понять, что такое искусственное расширение языка, не соответствующее его идеологии, лишь усложняет Лисп и лишает его как оригинальной ясности, так и эффективности.
Современные реализации Лиспа представляют собой большие программные комплексы, близкие к СА5£-системам. Несмотря на то что язык Лисп был придуман около 40 лет назад, он относится скорее к 4GL-классу.
Манипулирование объектами на абстрактном уровне, хотя и требует подчас не визуального, а конкретного кодирования, делает ненужным программирование рутинных операций, а наличие обширных библиотек, обеспечивающих быструю реализацию множества примитивов, позволяет получить более эффективный и надежный код, чем при ручном программировании аналогичных задач на C++. Например, программирование задач автоматического интеллектуального перевода на С может показаться совершенно абсурдным. (Интересно, а на чем пишут свои «переводчики» наши программисты?) Кстати, имеется большое число «компиляторов», переводящих текст задачи на Лиспе в код на языке С.
В профессиональных Лисп-системах имеются специальные библиотеки для поддержки графического интерфейса. Не обошлось и без объектно-ориентированных версий с описаниями классов «окно», «кнопка», «меню», «полоса прокрутки» и тому подобных. В этих системах обычно присутствуют и символьные отладчики, профилировщики и прочий инструментарий.
Конечно, и стоят такие системы недешево. Например, цена многоплатформной версии Allegro Lisp составляет 4500 долларов, система Golden Common Lisp для MS-DOS, Windows и OS/2 стоит 2000 долларов. Впрочем, существует и немалое количество некоммерческих компиляторов, например 32-разрядная версия Allegro Common Lisp for Windows (www.franz.com), GNU CL для Unix/Linux (ftp://ftp.cli.com/pub/gcl/) и другие.
Можно ожидать появления версий и для Интернета. Простой интерпретатор Лиспа на языке Java уже распространяется бесплатно, а в будущем наверняка появятся и более мощные сетевые диалекты. В силу своей простоты и эффективности этот красивый, но подзабытый в России язык заслуживает не меньшего внимания, чем те же «раскрученные» С и C++.
Smalltalk: идет волна...
Каждый язык программирования по-своему уникален. Одни языки создаются для конкретных целей, другие — как универсальное средство разработки. Некоторые языки созданы отдельными людьми, некоторые — комитетами специалистов. Языки могут нести оригинальные идеи или объединять в себе лучшие достижения прошлого с учетом развития компьютерной техники. Какие-то языки распространились по всему миру, а какие-то канули в небытие. Но практически каждый язык программирования таит в себе немало интересных особенностей, заслуживающих более тщательного рассмотрения.
Работы над языком Smalltalk начались в 1970 году в исследовательской лаборатории фирмы Xerox, а закончились спустя десять лет, воплотившись в окончательном варианте Smalltalk-80, оказавшимся родоначальником наиболее полноценной объектной идеологии.
В это же время специалисты Страны восходящего солнца решали, какой же язык выбрать в качестве основы для создания своей компьютерной системы пятого поколения, наверное, самого великого неудавшегося компьютерного проекта XX века. После долгих раздумий выбор пал на Пролог, что объяснялось в первую очередь возможностью легкой расширяемости языка. Как все казалось просто: заноси новые факты в базу и получай готовые решения! К сожалению, парадигма объектного мышления в те годы еще не властвовала над умами разработчиков. Фактически единственными объектными языкам были Симула-67 и Smalltalk, однако преимущества последнего не могли быть оценены по достоинству. В 70-е годы еще фактически не было опыта создания крупных распределенных систем обработки и анализа информации, когда практически невозможно реализовать серьезный проект без хорошей объектной модели. Кроме того, интерпретируемая структура Smalltalk, его ориентация на однопроцессорные компьютеры, по мнению японцев, совершенно не укладывалась в концепцию машин пятого поколения.
В некоторых областях информатики Smalltalk все же нашел применение, но через пять лет после его выхода был разработан язык C++, и про Smalltalk быстро забыли, настолько заманчивыми показались возможности нового языка, позволяющего использовать наработки из своего предшественника, обычного С. Из языка Smalltalk были взяты базовые идеи объектно-ориентированного программирования: инкапсуляция, наследование и полиморфизм, уже проверенные на практике. Немного была ограничена модель переноса свойств объектов от нескольких родителей, имевшая в других языках название множественного наследования. Правильность такого подхода подтвердилась сегодня, когда в языке Java (наиболее передовом, если выразить мнение ряда специалистов) множественное наследование отсутствует вообще. Кроме того, язык Java позаимствовал у своего собрата указатели, работа с которыми больше не является «беспределом» и строго контролируется. Из-за того, что двадцать лет назад в программировании властвовали «низкоуровневые» идеи, нацеленные на выжимание из кода максимальной производительности, язык Java не мог тогда «родиться от Си» в принципе.
Более привычный для программистов линейный синтаксис процедурного языка практически гарантировал языку C++ полный успех. По мере роста мощностей компьютеров стала возможной реализация проектов, которые ранее казались совершенно несбыточными. Возникла естественная потребность в адекватных средствах разработки и новых методологических подходах.