Реферат: М. Бен-Ари Языки программирования. Практический сравнительный анализ. Предисловие
М. Бен-Ари Языки программирования. Практический сравнительный анализ.
Предисловие
Значение языков программирования
Сказать, что хороший программист может написать хорошее программное обеспечение на любом языке, — это все равно, что сказать, что хороший пилот может управлять любым самолетом: верно, но не по существу. При разработке пассажирского самолета основными критериями являются безопасность, экономическая целесообразность и удобства; для военного самолета главное это летные качества и возможность выполнения боевой задачи; а при создании сверхлегкого самолета необходимо обеспечить низкую стоимость и простоту управления.
Роль языка в программировании принижается по сравнению с программной методологией и инструментальными средствами; и не только преуменьшается, но и полностью отвергается, когда утверждают, что хорошо разработанная система может быть одинаково хорошо реализована на любом языке. Но языки программирования — это не просто инструментальное средство;
это тот «материал», из которого создается программное обеспечение, то, что мы видим на наших экранах большую часть дня. Я верю, что язык программирования — один из наиболее, а не наименее важных факторов, которые влияют на окончательное качество программной системы. К сожалению, слишком у многих программистов нет достаточных языковых навыков. Они страстно любят свой «родной» язык программирования и не способны ни проанализировать и сравнить конструкции языка, ни оценить преимущества и недостатки современных языков и языковых понятий. Слишком часто можно услышать утверждения, демонстрирующие концептуальную путаницу: «Язык L1мощнее (или эффективнее) языка L2».
С этим недостатком знания связаны две серьезные проблемы разработки программного обеспечения. Первая — крайний консерватизм в выборе языков программирования. Несмотря на бурное развитие компьютерной техники и сложности современных программных систем, большинство программ все еще пишутся на языках, которые были разработаны около 1970 г., если
не раньше. Многие исследования в области языков программирования никогда не подвергались проверке практикой, и разработчики программ вынуждены с помощью различных инструментальных средств и методологий компенсировать устаревшую языковую технологию. Это примерно то же, что , отказ авиакомпании испытать реактивный лайнер на том основании, что старые винтомоторные самолеты и так могут прекрасно доставить вас куда нужно.
Вторая проблема состоит в том, что языковые конструкции используются без должного отбора, практически без учета надежности и эффективности. Это ведет к созданию ненадежного программного обеспечения, которое невозможно поддерживать, а также к неэффективности, которая устраняется скорее путем кодирования отдельных фрагментов программ на языке ассемблера, чем совершенствованием алгоритмов и парадигм программирования.
Языки программирования существуют только для преодоления разрыва в уровне абстракции между аппаратными средствами и реальным миром. Есть неизбежное противоречие между высшими уровнями абстракции, которые легче понять и безопаснее использовать, и низшими уровнями, более гибкими и зачастую допускающими более эффективную реализацию. Чтобы разработать или выбрать язык программирования, следует избрать соответствующий уровень абстракции, и нет ничего удивительного в том, что разные программисты предпочитают различные уровни и что какой-либо язык может подходить для одного проекта и не подходить для другого. Программисту следует хорошо понимать степень надежности и эффективности каждой конструкции языка.
^ Цель книги
Цель этой книги — научить читателя разбираться в языках программирования, анализируя и сопоставляя языковые конструкции, и помочь ему уяснить:
• Какие альтернативы доступны разработчику языка?
• Как реализуются языковые конструкции?
• Как их следует использовать?
Мы, не колеблясь, заявляем: накопленный опыт показывает, что одни конструкции предпочтительнее других, а некоторых следует избегать или, по крайней мере, использовать их с осторожностью.
Конечно, эту книгу не следует рассматривать как справочник по какому-либо конкретному языку программирования. Задача автора заключается в том, чтобы научить анализировать языки, не погружаясь в мелкие языковые частности. Книга также не является руководством по выбору языка для какого-либо конкретного проекта. Цель состоит в обеспечении учащегося концептуальными инструментальными средствами, необходимыми для принятия такого решения.
^ Выбор материала
Автору книги по языкам программирования неизбежно приходится обижать, по крайней мере 3975 из 4000, если не больше, изобретателей различных языков! Я сознательно решил (даже если это обидит 3994 человека) сосредоточить внимание на очень небольшом наборе языков, поскольку уверен, что на их примере смогу объяснить большинство языковых понятий. Другие языки обсуждаются только при демонстрации таких понятий, которые отсутствуют в языках, выбранных для основного рассмотрения.
Значительная часть книги посвящена «заурядным» процедурным (императивным, imperative) языкам; из этого класса выбраны два. Языки с низким уровнем абстракции представляет С, который обошел Fortran, прежде доминирующий в этой категории. Для представления более высокого уровня абстракции мы выбрали язык Ada с гораздо более четкими определениями, чем в широко известном языке Pascal.
Этот выбор оправдывает также то, что оба языка имеют расширения (C++ и Ada 95), которые можно использовать для изучения языковой поддержки объектно-ориентированного метода программирования, доминирующего в настоящее время.
К сожалению, (как я полагаю) большинство программ сегодня все еще пишутся на процедурных языках, но за последние годы качество реализаций непроцедурных (неимперативных) языков улучшилось настолько, что они могут использоваться для разработки «реального» программного обеспечения. В последних главах представлены функциональные (ML) и логические (Prolog) языки программирования с целью убедить учащихся, что процедурные языки не являются концептуальной необходимостью для программирования.
Теория синтаксиса языков программирования и семантики выходит за рамки этой книги. Эти важные предметы лучше оставить для более продвинутых курсов.
Чтобы избежать путаницы при сравнении примеров на разных языках, каждый пример сопровождается обозначением типа С++ . В разделах, где обсуждаются конструкции определенного языка, обозначения не даются.
^ О чем эта книга
Часть 1 является описательной. Она содержит определения и обзор языков и сред программирования. Во второй части подробно объясняются основные конструкции языков программирования: типы, операторы и подпрограммы. В части 3 рассматриваются более сложные понятия программирования, такие, как действительные числа, статический полиморфизм, обработка ошибок и параллелизм. В части 4 обсуждается программирование больших систем с акцентом на языковой поддержке объектно-ориентированного программирования. Заключительная часть 5 посвящена основным концепциям функционального и логического программирования.
^ Рекомендации по обучению
Необходимое условие для изучения этой книги — по крайней мере один год программирования на каком-либо языке типа Pascal или С. В любом случае, студент должен уметь читать С-программы. Также будет полезно знакомство со структурой и набором команд какого-либо компьютера.
На основе изложенного материала можно составить несколько курсов лекций. Части 1 и 2 вместе с разделами части 4 по модулям и объектно-ориентированному программированию могут послужить основой односеместрового курса лекций для второкурсников. Для продвинутых студентов можно ускорить изложение первой половины, с тем чтобы сосредоточиться на более трудном материале в частях 3 и 4. Углубленный курс, несомненно, должен включить часть 5, дополненную в большом объеме материалом по некоторому непроцедурному языку, выбранному преподавателем. Разделы, отмеченные звездочкой, ориентированы на продвинутых студентов.
Для большинства языков можно бесплатно получить компиляторы, как описано в приложении А. Студенты также должны быть обучены тому, как просмотреть команды ассемблера, генерируемые компиляторами.
Упражнения: поскольку эта книга о языках программирования, а не по программированию, то в упражнениях не делается акцент на проектировании программ. Вместо этого мы просим студентов покопаться в описаниях, сравнить языки и проанализировать, как компилятор реализует различные конструкции. Преподаватель может изменить упражнения и добавить другие согласно своему вкусу и доступности инструментальных средств.
Книга будет также полезна программистам, которые хотят углубить свои знания об инструменте, которым они ежедневно пользуются, — о языках программирования.
^ Примечание автора
Лично я предпочитаю более высокие уровни абстракции низким. Это — убеждение, а не предубеждение. Нам — разработчикам программного обеспечения — принадлежат печальные рекорды в вопросах разработки надежных программных систем, и я полагаю, что решение отчасти лежит в переходе к языкам программирования более высоких уровней абстракции. Обобщая высказывание Дейкстры, можно утверждать: если у вас есть программа в 100 000 строк, в которой вы запутались, то следует переписать ее в виде программы в 10 000 строк на языке программирования более высокого уровня.
Первый опыт я получил в начале 1970-х годов как член большой группы программистов, работающих над системой финансовых транзакций. Мы установили новую интерактивную систему, хотя знали, что она содержала ошибку, которую мы не могли найти. Спустя несколько недель ошибка была, наконец, обнаружена: оказалось, что изъяны в используемом языке программирования привели к тому, что тривиальная опечатка превратилась в несоответствие типов. Пару лет спустя, когда я впервые увидел Pascal, меня «зацепило». Мое убеждение в важности проблемы усиливалось всякий раз, когда я помогал ученому, потратившему впустую недели на отыскание ошибки в программе, причем в такой, которую, будь она на языке Pascal, нельзя было бы даже успешно скомпилировать. Конечно, несоответствие типов — не единственный источник ошибок программирования, но оно настолько часто встречается и так опасно, хотя и легко обнаруживается, что я считаю жесткий контроль соответствия типов столь же необходимым, как и ремень безопасности в автомобиле: использование его причиняет неудобство, но оно весьма незначительно по сравнению с возможным ущербом, а ведь даже самые лучшие водители могут попасть в аварию.
Я не хочу быть вовлеченным в языковые «войны», утверждая, что один язык лучше другого для какой-либо определенной машины или прикладной программы. Я попытался проанализировать конструкции языка по возможности объективно в надежде внести вклад в повышение уровня научных дискуссий относительно языков программирования.
Благодарности
Я хотел бы поблагодарить Кевлина А.П. Хеннея (Kevlin A.P Неппеу) и Дэвида В. Баррона (David W. Barron) за ценные замечания по всей рукописи, так же как Гарри Майрсона (Harry Mairson), Тамара Бенея (Tamar Benaya) и Бруриа Хабермена (Bruria Haberman), которые прочитали отдельные части. Я обязан Амирему Ехудаи (Amiram Yehudai), моему гуру в объектно-ориентированном программировании: он руководил мной во время многочисленных обсуждений и тщательно проверял соответствующие главы. Эдмон Шенберг (Edmond Schonberg), Роберт Девар (Robert Dewar) вместе со своей группой в NYU быстро отвечали на мои вопросы по GNAT, позволив мне обучиться и написать о языке Ada 95 еще до того, как стал доступен полный компилятор. Ян Джойнер (lan Joyner) любезно предоставил свой неопубликованный анализ языка C++, который был чрезвычайно полезен. Подобно моим предыдущим книгам, эта, вероятно, не была бы написана без LATEX Лесли Лампорта (Leslie Lamport)!
Мне посчастливилось работать с высоко профессиональной, квалифицированной издательской группой Джона Уайли (John Wiley), и я хотел бы поблагодарить всех ее членов и особенно моего редактора Гейнора Редвеса-Мат-тона (Gaynor Redvers-Mutton).
^ М. Бен-Ари
Реховот, Израиль
1 Введение
в языки
программирования
Глава 1
Что такое
языки программирования
1.1. Некорректный вопрос
Первый вопрос, который обычно задает человек, впервые сталкивающийся с новым языком программирования:
Что этот язык может «делать»?
Неявно мы сравниваем новый язык с другими. Ответ очень прост: все языки могут «делать» одно и то же — производить вычисления! В разделе 1.8 объяснена правомерность такого ответа. Однако, если все они могут выполнять одно и то же — вычисления — то, несомненно, причины существования сотен языков программирования должны быть в чем-то другом.
Позвольте начать с нескольких определений:
Программа — это последовательность символов, определяющая вычисление.
^ Язык программирования — это набор правил, определяющих, какие последовательности символов составляют программу и какое вычисление описывает программа.
Вас может удивить, что в определении не упоминается слово «компьютер»! Программы и языки могут быть определены как сугубо формальные математические объекты. Однако люди больше интересуются программами, чем другими математическими объектами типа групп, именно потому, что программу — последовательность символов — можно использовать для управления работой компьютера. Хотя мы настоятельно рекомендуем изучение теории программирования, здесь ограничимся, в основном, изучением того, как программы выполняются на компьютере.
Эти определения следует понимать в самом широком смысле. Например, сложные текстовые процессоры обычно имеют средство, которое позволяет запоминать последовательность нажатий клавиш и сохранять их как макрос, чтобы всю последовательность можно было выполнять с помощью единственного нажатия клавиши. Несомненно, это — программа, поскольку последовательность нажатий клавиш определяет вычисление, и в сопроводительной документации обязательно будет определен макроязык: как инициализировать, завершать и называть макроопределение.
Чтобы ответить на вопрос, вынесенный в название главы, вернемся к первым цифровым компьютерам, очень похожим на простые калькуляторы, какими сегодня пользуются для расчетов в магазине. Они работали по «жесткой» программе, которую нельзя изменить.
Наиболее значительным из первых шагов в усовершенствовании компьютеров была идея (автором которой считается Джон фон Нейман) о том, что описание вычисления (программу) можно хранить в памяти компьютера так же, как данные. Компьютер с запоминаемой программой, таким образом, становится универсальной вычислительной машиной, а программу можно изменять, только заменяя коммутационную доску, вводя перфокарты, вставляя дискету или подключаясь к телефонной линии.
Поскольку компьютеры — двоичные машины, распознающие только нули и единицы, то хранить программы в компьютере технически просто, но практически неудобно: каждая команда должна быть записана в виде двоичных цифр (битов), которые можно представить механически или электрически. Одним из первых программных средств был символический ассемблер. Ассемблер берет программу, написанную на языке ассемблера (каждая команда представлена в нем в символьном виде), и транслирует символы в двоичное представление, пригодное для выполнения на компьютере. Например, команду
load R3,54
означающую «загрузить в регистр 3 данные из ячейки памяти 54», намного легче прочитать, чем эквивалентную последовательность битов. Трудно поверить, но термин «автоматическое программирование» первоначально относился к ассемблерам, так как они автоматически выбирали правильную последовательность битов для каждого символа. Известные языки программирования, такие как С и Pascal, сложнее ассемблерных языков, потому что они «автоматически» выбирают адреса и регистры и даже «автоматически» выбирают последовательности команд для организации циклов и вычисления арифметических выражений.
Теперь мы готовы ответить на вопрос из названия этой главы.
Язык программирования — это механизм абстрагирования. Он дает возможность программисту описать вычисления абстрактно и в то же время позволяет программе (обычно называемой ассемблером, компилятором или интерпретатором) перевести это описание в детализированную форму, необходимую для выполнения на компьютере.
Теперь понятно, почему существуют сотни языков программирования: для двух разных классов задач скорее всего потребуются различные уровни абстракции, и у разных программистов будут различные представления о том, какими должны быть эти абстракции. Программист, работающий на С, вполне доволен работой на уровне абстракции, требующем определения вычислений с помощью массивов и индексов, в то время как составитель отчета отдает предпочтение «программе» на языке, содержащем функции текстовой обработки.
Уровни абстракции легко различить в компьютерных аппаратных средствах. Первоначально монтажные соединения непосредственно связывали дискретные компоненты, такие как транзисторы и резисторы. Затем стали использоваться стандартные подсоединяемые с помощью разъемов модули, за которыми последовали небольшие интегральные схемы. Сегодня компьютеры целиком собираются из горстки чипов, каждый из которых содержит сотни тысяч компонентов. Никакой компьютерщик не рискнул бы разрабатывать «оптимальную» схему из индивидуальных компонентов, если существует набор подходящих чипов, которые выполняют нужные функции.
Из концепции абстракции вытекает общее правило:
^ Чем выше уровень абстракции, тем больше деталей исчезает.
Если вы пишете программу на С, то теряете возможность задать распределение регистров, которая есть в языке ассемблера; если вы пишете на языке Prolog, то теряете имеющуюся в С возможность определить произвольные связанные структуры с помощью указателей. Существует естественное противоречие между стремлением к краткому, ясному и надежному выражению вычисления на высокоабстрактном уровне и стремлением к гибкости подробного описания вычисления. Абстракция никогда не может быть такой же точной или оптимальной, как описание низкого уровня.
В этом учебнике вы изучите языки трех уровней абстракции. Опуская ассемблер, мы начнем с «обычных» языков программирования, таких как Fortran, С, Pascal и Pascal-подобные конструкции языка Ada. Затем в части 4 мы обсудим языки типа Ada и С ++, которые позволяют программисту создавать абстракции более высокого уровня из операторов обычных языков. В заключение мы опишем языки функционального и логического программирования, работающие на еще более высоком уровне абстракций.
^ 1.2. Процедурные языки
Fortran
Первым языком программирования, который значительно превзошел уровень языка ассемблера, стал Fortran. Он был разработан в 1950-х годах группой специалистов фирмы IBM во главе с Джоном Бекусом и предназначался для абстрактного описания научных вычислений. Fortran встретил сильное противодействие по тем же причинам, что и все последующие предложения абстракций более высокого уровня, а именно из-за того, что большинство программистов полагало, что сгенерированный компилятором программный код не может быть лучше написанного вручную на языке ассемблера.
Подобно большинству первых языков программирования, Fortran имел серьезные недостатки в деталях самого языка, и, что важнее, в нем отсутствовала поддержка современных концепций структурирования модулей и данных. Сам Бекус, оглядываясь назад, говорил:
Мы просто придумывали язык по мере его осмысления. Мы расценивали проектирование языка не как трудную задачу, а просто как прелюдию к реальной проблеме: проектированию компилятора, который мог бы генерировать эффективные программы.
Однако преимущества абстракции быстро покорили большинство программистов: разработка программ стала более быстрой и надежной, а их машинная зависимость уменьшилась из-за абстрагирования от регистров и машинных команд. Поскольку самыми первыми на компьютерах рассчитывались научные задачи, Fortran стал стандартным языком в науке и технике, и только теперь на смену ему приходят другие языки. Fortran был неоднократно модернизирован (1966,1977,1990) с тем, чтобы адаптировать его к требованиям современных программных разработок.
^ Cobol и PL/1
Язык Cobol был разработан в 1950-х для обработки коммерческих данных. Он создавался комитетом, состоящим из представителей Министерства Обороны США, производителей компьютеров и коммерческих организаций типа страховых компаний. Предполагалось, что Cobol — это только временное решение, необходимое, пока не создан лучший проект; однако язык быстро стал самым распространенным в своей области (как Fortran в науке), причем по той же самой причине: он обеспечивал естественные средства выражения вычислений, типичных для своей области. При обработке коммерческих данных необходимо делать относительно простые вычисления для большого числа сложных записей данных, а по возможностям структурирования данных Cobol намного превосходит алгоритмические языки типа Fortran или С.
IBM позже создала язык PL/1, универсальный, обладающий всеми свойствами языков Fortran, Cobol и Algol. PL/1 заменил Fortran и Cobol на многих компьютерах IBM, но этот язык очень широкого диапазона никогда не поддерживался вне IBM, особенно на мини- и микроЭВМ, которые все больше и больше используются в организациях, занимающихся обработкой данных.
^ Algol и его потомки
Из ранних языков программирования Algol больше других повлиял на создание языков. Разработанный международной группой первоначально для общих и научных приложений, он никогда не достигал такой популярности, как Fortran, поскольку не имел той поддержки, которую Fortran получил от большинства производителей компьютеров. Описание первой версии языка Algol было опубликовано в 1958 г.; пересмотренная версия, Algol 60, широко использовалась в компьютерных научных исследованиях и была реализована на многих машинах, особенно в Европе. Третья версия языка, Algol 68, пользовалась влиянием среди теоретиков по языкам, хотя никогда широко не применялась.
От языка Algol произошли два важных языка: Jovial, который использовался Военно-воздушными силами США для систем реального времени, и Simula, один из первых языков моделирования. Но, возможно, наиболее известным его потомком является Pascal, разработанный в конце 1960-х Никлаусом Виртом. Целью разработки было создание языка, который можно было бы использовать для демонстрации идей объявления типов и контроля их соответствия. В последующих главах мы докажем, что эти концепции относятся к наиболее важным, когда-либо предлагавшимся в проектировании языков.
Как язык практического программирования Pascal имеет одно большое преимущество и один большой недостаток. Первоначальный компилятор языка Pascal был написан на самом языке Pascal и, таким образом, мог быть легко перенесен на любой компьютер. Язык распространялся быстро, особенно на создаваемых в то время мини- и микроЭВМ. К сожалению, как язык, Pascal слишком мал. Стандартный Pascal вообще не имеет никаких средств для деления программы на модули, хранящиеся в отдельных файлах, и поэтому не может использоваться для программ объемом больше нескольких тысяч строк. Компиляторы Pascal, используемые на практике, поддерживают декомпозицию на модули, но никаких стандартных методов для этого не существует, так что большие программы непереносимы. Вирт сразу понял, что модули являются необходимой частью любого практического языка, и разработал язык Modula. Modula (теперь в версии 3, поддерживающей объектно-ориентированное программирование) — популярная альтернатива нестандартным «диалектам» языка Pascal.
С
Язык С был разработан в начале 1970-х Деннисом Ричи, сотрудником Bell Laboratories, как язык реализации операционной системы UNIX. Операционные системы традиционно писали на ассемблере, поскольку языки высокого уровня считались неэффективными. Язык С абстрагируется от деталей программирования, присущих ассемблерам, предлагая структурированные управляющие операторы и структуры данных (массивы и записи) и сохраняя при этом всю гибкость ассемблерного низкоуровневого программирования (указатели и операции на уровне битов).
Так как система UNIX была легко доступна для университетов и написана на переносимом языке, а не на языке ассемблера, то она быстро стала популярна в академических и исследовательских учреждениях. Когда новые компьютеры и прикладные программы выходили из этих учреждений на коммерческий рынок, вместе с ними распространялись UNIX и С.
Язык С проектировался так, чтобы быть близким к языку ассемблера, и это обеспечивает ему чрезвычайную гибкость; но проблема состоит в том, что эта гибкость обусловливает чрезвычайную легкость создания программ со скрытыми ошибками, поскольку ненадежные конструкции не проверяются компилятором, как это делается на языке Pascal. Язык С — тонкий инструмент в руках профессионала и удобен для небольших программ, но при разработке на нем больших программных систем группами разработчиков разной квалификации могут возникнуть серьезные проблемы. Мы отметим многие опасные конструкции С и укажем, как не попадать в главные ловушки.
Язык С был стандартизирован в 1989 г. Американским Национальным Институтом Стандартов (ANSI); практически тот же самый стандарт был принят Международной Организацией по Стандартизации (ISO) годом позже. В этой книге делаются ссылки на ANSI С, а не на более ранние версии языка.
C++
В 1980-х годах Бьярн Строуструп, также из Bell Laboratories, использовал С как базис языка C++, добавив поддержку объектно-ориентированного программирования, аналогичную той, которую предоставлял язык Simula. Кроме того, в C++ исправлены многие ошибки языка С, и ему следует отдавать предпочтение даже в небольших программах, где объектно-ориентированные свойства, возможно, и не нужны. C++ — наиболее подходящий язык для обновления систем, написанных на С.
Обратите внимание, что C++ — развивающийся язык, и в вашем справочном руководстве или компиляторе, возможно, отсутствуют последние изменения. Обсуждаемый в этой книге язык соответствует книге Annotated C++ Reference Мanual Эллиса и Строуструпа (издание 1994 г.), которая является основой рассматриваемого в настоящее время стандарта.
Ada
В 1977 г. Министерство Обороны Соединенных Штатов решило провести унификацию языка программирования, в основном, чтобы сэкономить на обучении и стоимости поддержки операционных сред разработки программ для различных военных систем. После оценки существующих языков было принято решение провести конкурс на разработку нового языка, положив в основу хороший существующий язык, такой как Pascal. В конце концов был выбран язык, который назвали Ada, и стандарт был принят в 1983 г. Язык Ada уникален в ряде аспектов:
• Большинство языков (Fortran, С, Pascal) создавались едиными командами разработчиков и были стандартизованы уже после их широкого распространения. Для сохранения совместимости все случайные промахи исходной команды включались в стандарт. Ada же перед стандартизацией подверглась интенсивной проверке и критическому разбору.
• Многие языки первоначально были реализованы на единственном компьютере, и на них сильно повлияли особенности этого компьютера. Язык Ada был разработан для написания переносимых программ.
• Ada расширяет область применения языков программирования, обеспечивая обработку ошибок и параллельное программирование, что традиционно считалось (нестандартными) функциями операционных систем.
Несмотря на техническое совершенство и преимущества ранней стандартизации, язык Ada не достиг большой популярности вне военных и других крупномасштабных проектов (типа коммерческой авиации и железнодорожных перевозок). Язык Ada получил репутацию трудного. Это связано с тем, что он поддерживает многие аспекты программирования (параллелизм, обработку исключительных ситуаций, переносимые числовые данные), которые другие языки (подобные С и Pascal) оставляют операционной системе. На самом деле его нужно просто больше изучать. К тому же первоначально были недоступны хорошие и недорогие среды разработки для сферы образования. Теперь, когда есть бесплатные компиляторы (см. приложение А) и хорошие учебники, Ada все чаще и чаще встречается в учебных курсах даже как «первый» язык.
Ada 95
Ровно через двенадцать лет после принятия в 1983 г. первого стандарта языка Ada был издан новый стандарт. В новой версии, названной Ada 95, исправлены некоторые ошибки первоначальной версии, но главное — это добавление поддержки настоящего объектно-ориентированного программирования, включая наследование, которого не было в Ada 83, так как его считали неэффективным. Кроме того, Ada 95 содержит приложения, в которых описываются стандартные (но необязательные) расширения для систем реального времени, распределенных систем, информационных систем, защищенных систем, а также «числовое» (numerics) приложение.
В этой книге название «Ada» будет использоваться в тех случаях, когда обсуждение не касается особенностей одной из версий: Ada 83 или Ada 95. Заметим, что в литературе Ada 95 упоминалась как Ada 9X, так как во время разработки точная дата стандартизации не была известна
.
^ 1.3. Языки, ориентированные на данные
На заре программирования было создано и реализовано несколько языков, значительно повлиявших на дальнейшие разработки. У них была одна общая черта: каждый язык имел предпочтительную структуру данных и обширный набор команд для нее. Эти языки позволяли создавать сложные программы, которые трудно было бы написать на языках типа Fortran, просто манипулирующих компьютерными словами. В следующих подразделах мы рассмотрим некоторые из этих языков.
Lisp
Основная структура данных в языке Lisp — связанный список. Первоначаль-но Lisp был разработан для исследований в теории вычислений, и многие работы по искусственному интеллекту были выполнены на языке Lisp. Язык был настолько важен, что компьютеры разрабатывались и создавались так, чтобы оптимизировать выполнение Lisp-программ. Одна из проблем языка состояла в обилии различных «диалектов», возникавших по мере того, как язык реализовывался на различных машинах. Позже был разработан стандартный язык Lisp, чтобы программы можно было переносить с одного компьютера на другой. В настоящее время популярен «диалект» языка Lisp — CLOS, поддерживающий объектно-ориентированное программирование.
Три основные команды языка Lisp — это car(L) и cdr(L), которые извлекают, соответственно, начало и конец списка L, и cons(E, L), которая создает новый список из элемента Е и существующего списка L. Используя эти команды, можно определить функции обработки списков, содержащих нечисловые данные; такие функции было бы довольно трудно запрограммировать на языке Fortran.
Мы не будем больше обсуждать язык Lisp, потому что многие его основополагающие идеи были перенесены в современные функциональные языки программирования типа ML, который мы обсудим в гл. 16.
APL
Язык APL является развитием математического формализма, который используется для описания вычислений. Основные структуры данных в нем — векторы и матрицы, и операции выполняются над такими структурами непосредственно, без циклов. Программы на языке APL очень короткие по сравнению с аналогичными программами на традиционных языках. Применение APL осложняло то, что в язык перешел большой набор математических символов из первоначального формализма. Это требовало специальных терминалов и затрудняло экспериментирование с APL без дорогостоящих аппаратных средств. Современные графические интерфейсы пользователя, применяющие программные шрифты, решили эту проблему, которая замедляла принятие APL.
Предположим, что задана векторная переменная:
V= 1 5 10 15 20 25
Операторы языка APL могут работать непосредственно с V без записи циклов с индексами:
+ /V =76 Свертка сложением(суммирует элементы)
фV = 25 20 15 10 5 1 Обращает вектор
2 3 pV = 1 5 10 Переопределяет размерность
V 15 20 25 как матрицу 2x3
Векторные и матричные сложения и умножения также можно выполнить непосредственно над такими переменными.
^ Snobol, Icon
Первые языки имели дело практически только с числами. Для работы в таких областях, как обработка естественных языков, идеально подходит Snobol (и его преемник Icon), поскольку их базовой структурой данных является строка. Основная операция в языке Snobol сравнивает образец со строкой, и побочным результатом совпадения может быть разложение строки на подстроки. В языке Icon основная операция — вычисление выражения, причем выражения включают сложные операции со строками.
В языке Icon есть важная встроенная функция find(s1, s2), которая ищет вхождения строки s1 в строку s2. В отличие от подобных функций языка С find генерирует список всех позиций в s2, в которых встречается s1:
line := 0 # Инициализировать счетчик строк while s := read() { # Читать до конца файла
every col := find("the", s) do # Генерировать позиции столбца write (line, " ",col) # Write(line,col) для "the"
line := line+ 1
}
Эта программа записывает номера строк и столбцов всех вхождений строки "the" в файл. Если команда find не находит ни одного вхождения, то она «терпит неудачу» (fail), и вычисление выражения завершается. Ключевое слово every вызывает повторение вычисления функции до тех пор, пока оно завершается успешно.
Выражения Icon содержат не только строки, которые представляют собой последовательности символов; они также определены над наборами символов csets. Таким образом
vowels := 'aeiou'
присваивает переменной vowel (гласные) значение, представляющее собой набор указанных символов. Это можно использовать в функциях типа upto(vowels,s), генерирующих последовательность позиций гласных в s, и many(vowels,s), возвращающих самую длинную начальную последовательность гласных в s.
Более сложная функция bal подобна upto за исключением того, что она генерирует последовательности позиций, которые сбалансированы по «скобочным» символам:
bal(' +-*/','([', ')]',*)
Это выражение могло использоваться в компиляторе, чтобы генерировать сбалансированные арифметические подстроки. Если в качестве строки s задать
"х + (у [u/v] - 1 )*z", вышеупомянутое выражение сгенерирует индексы, соответствующие подстрокам:
x
x+(y[u/v]-1
Первая подстрока сбалансирована, так как она заканчивается «+» и не содержит никаких скобок; вторая подстрока сбалансирована, поскольку она завершается символом «*» и имеет квадратные скобки, правильно вложенные внутри круглых скобок.
Глава 2
Элементы
языков программирования
2.1. Синтаксис
Как и у обычных языков, у языков программирования есть синтаксис:
Синтаксис языка (программирования) — это набор правил, которые определяют, какие последовательности символов считаются допустимыми выражениями (программами) в языке.
Синтаксис задается с помощью формальной нотации.
Самая распространенная формальная нотация синтаксиса — это расширенная форма Бекуса — Наура (РБНФ). В РБНФ мы начинаем с объекта самого верхнего уровня, с программы, и применяем правила декомпозиции объектов, пока не достигнем уровня отдельного символа. Например, в языке С синтаксис условного оператора (if-оператора) задается правилом:
if-onepamop :: = if (выражение) оператор [else оператор]
Имена, выделенные курсивом, представляют синтаксические категории, а имена и символы, выделенные полужирным шрифтом, представляют фактические символы, которые должны появиться в программе. Каждое правило содерж
еще рефераты
Еще работы по разное
Реферат по разное
Мбоу «Гляденская оош №11»
17 Сентября 2013
Реферат по разное
Комисси я по мелкорозничной и ярмарочной торговле
17 Сентября 2013
Реферат по разное
Ожности по повышению эффективности усвоения инженерных знаний и умений, подготовки компетентных и конкурентоспособных специалистов для современного производства
17 Сентября 2013
Реферат по разное
Возникла и развивалась в недрах философии как единой науки, объединявшей всю совокупность представлений людей об окружающем мире и самом человеке, его мышлении
17 Сентября 2013