Путешественник во времени Майк Бедфорд возвращается на 65 лет назад, к зарождению языков высокого уровня и рассматривает АЛГОЛ — язык, положивший начало революции.
В этой статье мы переводим часы на 1958 год. Это приведет нас к самым ранним дням появления языков высокого уровня. Если не принимать во внимание пару языков, о которых сегодня мало кто слышал, и которые, вероятно, не были слишком влиятельными, только FORTRAN появился раньше, причем всего на год. Другой классический язык высокого уровня той эпохи — COBOL, был выпущен только в следующем году. Творение 1958 года, о котором идет речь — это ALGOL и мы должны признать, что он так и не захватил мир. Но в отличие от FOCAL, ALGOL — это не просто сноска в учебниках истории. Несмотря на то, что он не смог завоевать веру среди растущей группы программистов на FORTRAN, он оказал огромное влияние, проложив путь для многих других языков, которые последовали за ним, включая практически все современные новейшие и лучшие.
Представляем АЛГОЛ
Мы уже упоминали о языке под названием АЛГОЛ — что расшифровывается как ALGOrithmic Language — но сегодня ни один язык так не называется. Язык, представленный в 1958 году, сейчас называется ALGOL 58, хотя первоначально он назывался IAL, от этого названия отказались, потому что аббревиатура была непроизносимой, за ним последовал ALGOL 60, а затем ALGOL 68, на котором мы и сосредоточились. Концепция развивающегося программного языка, каждая итерация которого сопровождается номером версии или годом ее появления, не является чем-то незнакомым.
АЛГОЛ 60 не был объектно-ориентированным языком, как и любой из АЛГОЛов, но он оказал большое влияние на разработку Simula. Как следует из названия, Simula был языком, разработанным специально для моделирования; однако он ввел объектную ориентацию и, как таковой, считается влиятельным во внедрении подхода ООП, который сейчас воспринимается как должное. |
АЛГОЛ 58 был доказательством концепции, но мало кто имел возможность его использовать. Был создан компилятор для компьютера Konrad Zuse Z22 и для Librascope LGP-30 в Дартмутском колледже, где позже был разработан BASIC, но на этом все. Поэтому ALGOL 60 можно считать первым практическим языком ALGOL, и хотя он использовался в научном сообществе, он никогда не пользовался большим успехом, в немалой степени из-за вялой поддержки семейства языков ALGOL со стороны IBM. Другим основным языком ALGOL был ALGOL 68. Он также использовался в академических кругах, но не в значительной степени в других местах, частично из-за критики, что он слишком сложен. Однако, и это возвращает нас к нашим ссылкам на версии FORTRAN, семейство ALGOL не было разработано с учетом обратной совместимости, поэтому ALGOL 68 не был супермножеством ALGOL 60.
Платформы АЛГОЛАТот факт, что ALGOL 60 был впервые использован на мэйнфреймах, не должен удивлять. В конце концов, первый в истории миникомпьютер DEC PDP-8 появился только в 1965 году, а персональные компьютеры ожидали еще десятилетие. Даже ALGOL 68 появился в эпоху, когда слово компьютер было практически синонимом мэйнфреймов. Помимо малоизвестного Konrad Zuse Z22, на котором впервые появился ALGOL 58, языки ALGOL появились на большинстве семейств мейнфреймов, хотя в мире IBM System/360 он был сравнительно незначительным игроком. В Великобритании, к примеру, он пользовался умеренным успехом на мейнфреймах серии ICL 1900, в немалой степени потому, что эти машины широко использовались в академических кругах — одном из основных секторов, в котором языки ALGOL пользовались успехом. Несмотря на все это, ALGOL, безусловно, продвинулся за пределы мэйнфрейма, и не только в недавних попытках сохранить его для будущих поколений. Существуют ссылки на ALGOL 60 на PDP-8 и ALGOL 68 на его преемнике PDP-11, хотя не похоже, что они были особенно значимыми на этих платформах. Особенно интересен ALGOL-M, который, несмотря на то, что никогда не был официальным языком ALGOL, был разработан как близкий к ALGOL 60. Он был разработан в 1977 году Джоном П. Флинном и Марком С. Моранвиллом из Военно-морской аспирантуры в Монтерее, Калифорния. Он стал первым в истории языком высокого уровня для микрокомпьютера и был выпущен в свободном доступе для CP/M на машинах на базе 8088. |
Эта краткая история не слишком хорошо объясняет, почему языки ALGOL считаются столь важными; на самом деле, это скорее говорит об обратном. Но когда мы начинаем изучать АЛГОЛ, мы обнаруживаем особенность, которая отличает их от ранних версий FORTRAN и нескольких языков, последовавших за АЛГОЛом, таких как BASIC и COBOL. Оператор IF
в первоначальной версии FORTRAN предусматривал переход к одному из трех номеров строк в зависимости от того, был ли результат вычисления отрицательным, нулевым или положительным. Конечно, не существовало понятия о том, что оператор IF
выполняет блок из нескольких строк кода — фактически, единственным оператором в старом FORTRAN, который имел хоть какое-то понятие о блоке операторов, была инструкция DO
.
Такое отсутствие блоков не способствовало улучшению читаемости кода читабельности кода и со временем вызвало критику, что FORTRAN и некоторые другие ранние языки пропагандировали спагетти-код. Эта фраза относится к исходному коду, который неизменно сложен для понимания и сопровождения, в котором широко используются операторы GOTO
или другие инструкции, заставляющие переходить к указанной строке (см. диаграмму примера спагетти-кода FORTRAN). Сегодня мы воспринимаем это как должное, но АЛГОЛ проложил новый путь в качестве структурированного языка. Это означало, например, что оператор IF
не ограничивается выполнением одной инструкции, если условие истинно, а вместо этого могла выполняться группа инструкций.
Мы могли бы ассоциировать FORTRAN с спагетти-кодом при объяснении преимущества, предлагаемые АЛГОЛ языки, но это немного несправедливо по отношению к этому почтенного языку. FORTRAN продолжает развиваться и сделал свои первые шаги к поддержке структурированного программирования с FORTRAN 77. |
Другой аспект структурного подхода заключается в том, что программа может быть построена в виде нескольких блоков, которые могут быть вложенными, при этом переменные, объявленные в блоке, могут быть доступны только в пределах этого блока. Несмотря на отсутствие поддержки ALGOL — его дизайн вдохновил Pascal, разработанный в 1970 году и имевший значительно больший успех, чем ALGOL. Он также повлиял на CPL, который через BCPL превратился в C и, в конечном итоге, в C++. Сегодня трудно представить себе какой-либо основной язык, который бы не восходил к АЛГОЛУ.
АЛГОЛ 68 года
Мы делаем акцент на АЛГОЛ 68 не потому, что он обязательно был лучшим из двух основных языков АЛГОЛ (некоторые эксперты придерживаются противоположного мнения), а потому, что на сегодняшний день лучшая на сегодняшний день реализация Linux — это ALGOL 68.
Если вы хотите поработать с ALGOL 68, мы рекомендуем вам использовать Algol 68 Genie. Мы установили его под Ubuntu 22.04 LTS — в репозитории он называется algol68g (в Manjaro тоже есть и с таким же названием), но если у вас проблемы с вашим дистрибутивом, посмотрите на https://jmvdveer.home.xs4all.nl/en.algol-68-genie.html. Документация также находится по этому адресу. Это не IDE, а интерпретатор командной строки, хотя это слово не используется так, как оно было бы использовано для описания классического BASIC-интерпретатора. На самом деле это инструмент для компиляции кода с целью получения файла объектного кода, который, при условии отсутствия ошибок компиляции, немедленно выполняется, и результат появляется в окне терминала. Например, для компиляции и выполнения кода, который вы ввели через текстовый редактор, вы бы набрали что-то вроде a68g mycode.a68
.
Как и для многих других языков, которые мы рассматриваем, если вы не хотите устанавливать интерпретатор локально — есть возможность попробовать его онлайн. Прежде чем двигаться дальше, было бы неплохо опробовать какой-нибудь надежный код локально или онлайн. Rosetta Code — отличный источник подходящего кода. Мы попробовали Anti-Primes из Rosetta Code на TIO и получили ожидаемый ответ, как видно на скриншоте либо для просмотра можно перейти по ссылке.
«Языки» ALGOL
Семейство языков программирования ALGOL было формально определено в так называемом эталонном языке, в то время как язык публикации использовался для публикации кода, а аппаратный язык представлял код как написанный для конкретной платформы, который, следовательно, может быть скомпилирован и выполнен. Одна из основных областей, в которых эти языки различаются — это представление ключевых слов, которые в АЛГОЛе не являются зарезервированными словами, поэтому требуется средство, например, для различия IF
как утверждения и IF
как идентификатора, такого как имя функции или переменной (признаем, что это не очень хорошая идея). Такие конвенции, как подчеркивание или символ подчеркивания, использовались в языке ссылок, но поскольку он предназначен в основном для использования писателями компиляторов, а не программистами, мы будем удобно игнорировать его.
Сегодня язык публикации и аппаратный язык часто взаимозаменяемы, но так было не всегда. Обычным способом публикации кода АЛГОЛ было использование прописных букв для ключевых слов и строчных букв для идентификаторов. Этой традиции придерживаются в более поздних реализациях, таких как Algol 68 Genie, и именно так мы будем показывать код здесь. Однако в ранние времена было невозможно использовать эту традицию для аппаратного языка, поскольку большинство считывателей карт мейнфреймов и линейных принтеров не поддерживали нижний регистр.
Для аппаратного языка было принято решение окружать ключевые слова одинарными кавычками. Так, например, утверждение IF a < 0 THEN ...
превращается в 'IF' a < 0 'THEN' ...
. В результате одинарные кавычки уже нельзя было использовать нормально, поэтому открывающие и закрывающие кавычки превратились в '('
и ')'
. Это не улучшило читабельность, поэтому, например, для печати текстовой строки вам может понадобиться такое причудливое выражение, как PRINT TEXT ('('HELLO')')
. Мимоходом вы заметили, что PRINT
не заключено в одинарные кавычки, что, вероятно, покажется вам удивительным.
Это потому, что формальное определение АЛГОЛа не включало операторов ввода/вывода, оставляя его реализацию на усмотрение пользователя в виде функции для конкретного оборудования. Последовавшее за этим отсутствие переносимости было еще одной часто упоминаемой причиной отсутствия успеха АЛГОЛа, за исключением того, что он оказал большое влияние на будущие языки. Еще кое-что, что появилось в эталонном языке, но было изменено в аппаратном, чтобы справиться с ограниченным набором символов 60-х годов, были такие символы, как ≤,
≥
и ≠,
используемые в условных выражениях. Необычные символы использовались и для других целей, но мы не будем в них углубляться. Интересно, что несмотря на то, что все эти необычные символы доступны на современных платформах, они по-прежнему не используются в Algol 68 Genie, и, возможно, в других современных аппаратных языках — вероятно потому, что их нелегко набирать.
Кодирование на АЛГОЛ 68
Теперь мы увидели достаточно, чтобы приступить к рассмотрению кода на языке ALGOL 68. Учитывая, что это было главное новшество языков ALGOL, мы в основном будем рассматривать его поддержку блоков и, следовательно, устранение спагетти-кода. Проще говоря, блоки состоят из списка выражений, сгруппированных определенным образом, чтобы они могли появляться вместо отдельных выражений — например, в операторе IF
. Во многих наиболее распространенных современных языках, таких как Java, C и C++, такие выражения группируются с помощью открывающих и закрывающих фигурных скобок, а в Python — с помощью отступов.
АЛГОЛ отличается тем, что определяет блок выражений — он же последовательная конструкция — способом, который, как это ни странно, отличается от одного выражения к другому, хотя обоснование одно и то же. Смысл в том, что блоки завершаются ключевым словом, являющимся обратным вариантом открывающего ключевого слова. Наша первая программа иллюстрирует это. Ее цель — вычислить первые 20 пирамидальных чисел. Это количество шаров в четырехгранной пирамиде различной высоты. Значение этих чисел равно сумме квадратов всех целых чисел до высоты — так, например, первые несколько чисел равны 1, 5, 14, 30 и 55.
# Calculate first 20 pyramidal numbers # INT pyramid := 0; FOR i FROM 1 TO 20 DO pyramid := pyramid + i^2; print( (pyramid, newline ) ) OD
Наша ссылка на перевернутую версию открывающего ключевого слова должна быть понятна. Блок утверждений вводится с помощью DO
, а завершается с помощью OD
. Далее мы рассмотрим простой код. который вводит оператор IF
. Его цель — сгенерировать 20 случайных чисел в диапазоне от 0 до 9, и если число окажется нечетным, вывести сообщение об этом.
# Identify odd numbers among 20 random integers # INT randnum; FOR i FROM 1 TO 20 DO randnum := ROUND (random*10); IF ENTIER(randnum/2) /= randnum/2 THEN print( (randnum, “ is odd”, newline ) ) FI OD
Исходя из нашего опыта с FOR ... DO ... OD
, вы, возможно, ожидали увидеть IF ... THEN ... NEHT
, но, как видите, на самом деле мы имеем IF ... THEN ... FI
. Однако это не так уж нелогично, как может показаться, как мы увидим в нашем следующем примере, развивающем наш предыдущий код, не только определяя нечетные числа, но и перечисляя все сгенерированные случайные целые числа и определяя их как нулевые, нечетные или четные.
# Categorise 20 random integers as zero, odd or even # INT randnum; FOR i FROM 1 TO 20 DO randnum := ROUND (random*10); IF randnum = 0 THEN print( (randnum, “ is zero”, newline ) ) ELIF ENTIER(randnum/2) = randnum/2 THEN print( (randnum, “ is even”, newline ) ) ELSE print( (randnum, “ is odd”, newline ) ) FI OD
Теперь мы используем расширенную версию оператора IF
, включающую также ELIF (else if) ... THEN
и также ELSE
. Тот факт, что и ELIF ... THEN
и ELSE
могут также завершать группу утверждений после IF ... THEN
, раскрывает смысл отсутствия терминатора NEHT
. Код должен быть понятен, если мы укажем что ENTIER
— это стандартная функция для возврата целой части вещественного числа, а /=
означает «не равно».
Многие эксперты считают C, а следовательно, и большинство популярных сегодня языков, прямыми потомками ALGOL 60. Это делает Pascal, который также был вдохновлен АЛГОЛом, но по другой линии происхождения, чем-то вроде тупика. Однако было бы неправильно игнорировать его. Названный в честь французского математика Блеза Паскаля, заложившего основы теории вероятностей, язык получил значительный первоначальный успех, особенно для преподавания, после своего появления на сцене в 1970 году. Несмотря на то, что он был разработан всего через два года после ALGOL 68, его применение не могло быть более разным. Список платформ и реализаций мог бы быть длинным, и, что очень важно, в результате его большей долговечности чем ALGOL, многие из этих продуктов были нацелены на пользователей ПК. Одним из самых влиятельных был Turbo Pascal от Borland для MS-DOS/Windows, хотя в конечном итоге был выпущен порт для Linux под названием Kylix — оба продукта в настоящее время заброшены. Сегодня для Linux доступны Free Pascal и связанная с ним IDE Lazarus, а также GNU Pascal Compiler. С технической точки зрения синтаксис Pascal похож на синтаксис АЛГОЛа, за исключением того, что способы разграничения блоков в АЛГОЛе ( |
Мы не будем приводить пример кода, но следует также упомянуть инструкцию CASE
, которая завершается ESAC
, а также WHILE
, не являющуюся самостоятельной инструкцией, а скорее необязательной частью оператора DO
, как и FOR
, поэтому она завершается OD
. Также следует упомянуть конструкцию BEGIN ... END
, которая может быть записана как ( ... )
. Она часто используется для заключения всей программы, и, хотя мы подозреваем, что изначально она была обязательной, в Algol 68 Genie это не так. Однако она обязательна для тела определения процедуры, и её можно использовать для сегментации программы.
Тот факт, что в ALGOL 68 есть несколько способов открытия и закрытия группы утверждений, был подвергнут критике, и, признаться, это кажется несколько запутанным по сравнению с почти повсеместным использованием символов { ... }
во многих современных языках. Однако это не должно заставить нас забыть о том, насколько революционными и влиятельными были языки АЛГОЛ. И, если быть совсем честным, не потребуется много времени, чтобы эта причуда ALGOL 68 стала второй натурой.
Переходим к вам
Надеемся, что мы вдохновили вас попробовать свои силы в программировании на АЛГОЛ 68, и если это так, то есть несколько способов перейти к этому. И вот один из лучших способов начать, прежде чем писать свой собственный код с нуля — это, конечно же, взять несколько работающих программ и каким-либо образом их модифицировать. Отличным источником программ на ALGOL 68 является Rosetta Code, где вы найдете список на пяти страницах, с примерно 200 программами на странице.
Все программы Rosetta Code, похоже, только текстовые, но по мере изучения вы должны поэкспериментировать с добавлением графических элементов в свой код. Algol 68 Genie может работать с библиотекой GNU libplot, и в документации, которую вы можете найти по адресу, есть все подробности. На самом деле, поскольку ALGOL 68 поддерживает комплексные числа — и да, мы понимаем, что, приложив немного больше усилий, можно легко выполнять сложную арифметику в языках, поддерживающих только вещественные числа — одна из идей для первой программы на ALGOL 68, которую вы пишете с нуля, — это реализовать код для рисования множества Мандельброта. Это не такое распространенное упражнение по кодингу, каким оно было когда-то, но это не умаляет того удивительного зрелища, откроющегося перед вами при запуске собственного кода. Интересно также отметить, что множество Мандельброта было открыто только в 1978 году — через 10 лет после появления ALGOL 68.
Интересная статья. Но совершенно непригодная для чтения. Языковые ошибки (в русском языке, не в ALGOL), доходят до уровня полной непонятности фрагментов текста.