В защиту PL/1

Предисловие

Данная статья попалась мне в http://www.softpanorama.org/Lang/pl1.shtml. К сожалению и к своему стыду, я так и не смог найти имени автора. Но, конечно, этот автор не Безруков (хозяин сайта), а неведомый мне американский (или английский?) ИТ-специалист старшего поколения. Английский текст был пропущен через «Гугл-переводчик», а затем «литературно» обработан.

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

Жесткий, даже нарочито оскорбительный тон по отношению к известным специалистам (сами они, впрочем, тоже обзывают!), тем не менее, показывает, что не все и сейчас согласны с «общепринятыми» вроде бы истинами в программировании.

Я думаю, многим будет небезынтересно узнать, откуда пошли многие возможности современных языков программирования и как они задумывались изначально. А как программист, до сих пор использующий PL/1 в работе на обычном персональном компьютере, я во многом (но не во всем!) согласен с автором статьи и тоже, например, считаю, что развитие языков программирования было бы более эффективным, если бы фундаментом этого развития стали не примитивные языки типа Си, а появившийся полвека назад язык PL/1.

Введение

PL/1 — серьезный язык с двумя чрезвычайно высококачественными компиляторами, созданными IBM. К сожалению, он пережил трагическую, незаслуженную судьбу и сегодня почти забыт. Он должен был заменить Кобол, но ему никогда не удавалось исполнить эту роль, за исключением СССР и стран Восточного блока. Как и любая инновационная технология, язык получил серьезный ущерб от неправильного маркетинга IBM (IBM проделала огромную работу по разработке языка и компиляторов, но чрезмерная жадность обрекла эти усилия на неудачу). IBM должна была бы сделать отладочный компилятор бесплатным и брать деньги только за оптимизирующий компилятор. Можно было сделать и ещё один полезный шаг — перевести старый отладочный компилятор в ранг «общественного достояния», т.е. полностью открыть.

До разработки PL/1 все предыдущие языки были сосредоточены на одной конкретной области применения, такой как численные расчеты, искусственный интеллект или бизнес. PL/1 был первым, разработанным как универсальный язык, и это был огромный прорыв, поскольку это была первая и успешная попытка создать язык, который можно было бы применять в различных областях. Опять же, во многих областях это было настолько далеко продвинуто для своего времени (это язык более высокого уровня, чем Cи, который был создан десятилетие спустя на основе опыта его создателей по использованию PL/1 в Multics), что даже с трудом воспринималось. Другим фактором, который способствовал гибели PL/1, было отсутствие бесплатных высококачественных компиляторов. Мы хорошо осознаем сложность таких компиляторов как таковых. Поэтому коммерческие компиляторы были довольно дорогими. Однако в Восточной Европе они поставлялись как часть стандартного дистрибутива ОС для мэйнфреймов. Это способствовало огромному успеху PL/1 в этом регионе и показывает, что если бы IBM предоставила компиляторы PL/1 бесплатно, язык мог бы быть значительно более успешным, чем в действительности стал в США.

Язык также пострадал от вводящих в заблуждение или просто глупых «гуру» сообщества пользователей языков программирования, таких как «отец структурированного программирования». Язык стал любимой мишенью ошибочной критики со стороны «пуристов» от языкового дизайна. Никлаус Вирт и Эдгар Дейкстра были особенно влиятельными и особенно заблуждающимися. Эдгар Дейкстра, несмотря на свои ранние достижения, был причиной особенно разрушительных последствий из-за своего неверного, почти религиозного рвения к доказательствам правильности программ и как создатель первого культа «компьютерной науки», которая извращала информатику в течение десятилетия или более.

Основной причиной неудачи языка был тот факт, что он, вероятно, опережал свое время лет на 20, а компиляторы были слишком сложными, что ухудшало переносимость. Особенно неудачной, по мнению ядовитых критиков, была идея «без зарезервированных ключевых слов» и чрезмерная гибкость синтаксиса оператора описания. Тем не менее, важно понимать, что это был очень инновационный язык с очень инновационными компиляторами, который, возможно, слишком сильно опередил свое время, чтобы выжить.

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

И это не единственный отличный продукт, который почти исчез. В этом смысле падение его популярности не сильно отличается от упадка двух других инновационных и интересных продуктов IBM: VM/CMS и OS/2.

Теперь и книги, и компиляторы на PL/1 стали редкостью, хотя оптимизирующие и отлаживающие компиляторы IBM на мэйнфреймах по-прежнему доступны и остаются непревзойденным шедевром разработки программного обеспечения.

Например, такая возможность, как обработка исключений, была настолько хорошо интегрирована в язык, что большинство программистов действительно регулярно использовали её. В этом смысле PL/1 был первым языком, который узаконил исключения как особенность языков программирования (при этом, как ни странно, он не содержал явных сопрограмм в качестве конструкции языка программирования, хотя обработчики исключений «определяемые программистом» были очень похожи на них).

PL/1 также имеет хорошие возможности обработки строк, и к этому языку можно отнести появление наиболее распространенных функций обработки строк (substr , index , length и trim) в их современной форме. Правда, появилась одна проблема, которая была связана с решением о реализации длин строк в компиляторах IBM как префиксов в их начале. Это была своего рода преждевременная оптимизация, в результате которой было создано два класса строк: короткие (до 255 — длина может быть сохранена одним байтом) и средние (с длиной, хранящейся в двух первых байтах).

Возможности PL/1 существуют во многих других языках и, прежде всего, в Cи, что семантически можно рассматривать как прямую производную (ограниченное подмножество) PL/1. Я хотел бы подчеркнуть, что PL/1 (как язык системного программирования для Multics) имел большое влияние на Cи — один из наиболее широко используемых компилируемых языков программирования, и многие из идей PL/1 прямо или косвенно нашли свое отражение в других языках программирования, например, в Perl Ларри Уолла.

У меня нет информации о возможном влиянии PL/1 на Ларри Уолла, но, по-моему, он продемонстрировал хорошее понимание, если не структуры и семантики PL/1, то, по крайней мере, философии PL/1, а именно: в какой-то момент простота становится саморазрушительной, и парадоксально, что сложные неортогональные языки упрощают использование по сравнению с «расширениями» более простого языка. Несмотря на сложность, они лучше интегрированы, а ошибки лучше диагностируются, поскольку компилятор распознает эти структуры и функции как элементы языка и может выполнять некоторые статические проверки.

Давайте немного поговорим о скрытой аналогии между PL/1 и Perl. PL/1 был первым широко распространенным неортогональным языком (т.е. с множеством разных способов сделать одно и то же), и в этом смысле его можно рассматривать как предшественник Perl и тесно связанный с философией Perl. Исторически это было, вероятно, ответной реакцией на Unix, слишком далеко продвигающей «простоту» и побеждающей других таким образом. Ключевой вопрос в этом отношении, который следует задать, заключается в следующем: что же такого простого в двухстах «простых» утилитах Unix? Только их общее количество и различия (часто незаметные) в подходах к именованию и обработке параметров (без железного кулака корпоративного стандарта, как в спецификации мэйнфреймов IBM или интерфейсов Microsoft GUI) сделали их совершенно непонятным беспорядком. В мире нет и не может быть человека, который знает их всех. Это слишком много для человеческого мозга.

В этом смысле сложность, перенесенная из библиотек и утилит непосредственно в язык программирования, может принести пользу сообществу программистов: таким образом вы можете, если не избежать, но, по крайней мере, несколько приручить непроницаемый лабиринт библиотек/классов и т.д.

Кроме того, PL/1 свободен от любых религиозных доктрин, и это делает его желанным членом семейства языков программирования, в отличие от всех этих языков со строгим типом или ОО-языков («обещают много, предоставляют мало»), таких как Java. Грубая ошибка считать, что дизайн Java слишком очевиден, хотя, по правде говоря, Java изначально создавался как небольшой язык для встроенного приложения и не был разработан как «универсальный» язык программирования, которым он стал позже (и заменой Коболу для коммерческого программирования), и который представил ОО в массы и полностью их с ним связал. Правоверные в ОО, вероятно, должны прекратить читать эту страницу в этот момент :-).

Атаки на PL/1 фанатиков от «структурированного программирования» и «доказательств правильности программ»

Значительный удар по PL/1 был нанесен в начале 70-х годов религиозными фанатиками, связанными с догмами «структурированного программирования» и, особенно, Эдсгером В. Дейкстрой как вдохновителем «безумия верификации». Сейчас трудно понять, как почти вся компьютерная наука была обманута этой примитивной религиозной доктриной. Но это оказалось правдой и довольно хорошо продемонстрировало, что добродетели, приписываемые академическим ученым, слишком раздуты. Еретики, которые готовы быть сожженными на костре в защиту правды, так же редки в академическом сообществе, как и среди простых людей. Может быть ещё реже. Полная коррупция академической экономики, превращение большинства из них в интеллектуальных защитников интересов финансовой олигархии, которую мы наблюдали с 1980 года, говорят об этой довольно обычной и понятной ситуации. И компьютерные ученые не так уж отличаются от других. Они также зависят от грантов и хотят владеть умами любой ценой. Что требует определенных компромиссов.

Эдсгер В. Дейкстра вдохновил «безумие верификации», которое было в основном связано с фиктивным математическим [рукоблудием — правка автором сайта], называемой «доказательствами правильности программ». Идея была «простой, привлекательной и неправильной», и из-за этого вскоре стала более модной, чем пьяные драки в пабах в Англии. Это привлекло огромное количество продавцов воздуха и мошенников от информатики, которые часто наводняли факультеты информатики и исключали полезные исследования. Вначале структурированное программирование давало положительный эффект для развития программирования (например, оно помогло ввести более богатый набор программных средств управления и структурирования в языках, и PL/1 снова стал пионером в этой области). Но в дальнейшем это привело к созданию нереалистичных или просто вредных ожиданий (что количество ошибок в программе без операторов goto меньше, чем для программы со многими операторами goto, но на самом деле значение имеет лишь использование структурированных управляющих операторов, причем, если некоторые из них не доступны на языке, они должны быть эмулированы с использованием тех самых операторов goto).

Эдсгер В. Дейкстра сыграл роль яростного аятоллы. Этот противоречивый персонаж имел религиозное рвение Лютера, но был более заблуждающимся. И в разгар своего заблуждения аятолла Дейкстра полностью потерял здравый смысл и издал фетву, в которой он объявил PL/1 «смертельной болезнью». Эти ядовитые шипы религиозного пыла повредили статусу многих языков и помогли более примитивным языкам с гораздо более простыми компиляторами, такими как Паскаль и Cи, получить и место, и аудиторию.

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

Компилятор для Cи был также намного проще, чем компилятор для сопоставимого подмножества PL/1, (такого как PL/M), и свободно распространялся с исходным кодом Unix. Создатели Cи отказались от фальшивой идеи «нет зарезервированных ключевых слов» и значительно упростили синтаксис объявления переменных, чем не только удалили «бородавки» языка PL/1, но и значительно сэкономили на простоте компилятора. Но сокращая язык до подмножества, подходящего для системного программирования, они сократили слишком много, и получились грабли, которые охотятся на Cи и C++ программистов по сей день. Они также допустили некоторые грубые ошибки в разработке синтаксиса языка, так как нет механизма для множественного закрытия блоков {} с помощью одного символа-скобки, такого как: «конец-метка» в PL/1. А в качестве разделителей для условных выражений в операторах if используются круглые скобки. Именно эти две ошибки стоят программистам на Си огромного количества потерянных часов в попытках найти ошибки, которых просто не должно существовать в правильно спроектированном языке. Они также игнорировали некоторые важные эвристики для обнаружения ошибок, изобретенные в оптимизирующем компиляторе PL/1.

Догма структурированного программирования и догма «безумия верификации» были двумя первыми религиозными движениями в программировании, но, к сожалению, не были последними. Позже объектно-ориентированная (ОО) парадигма стала модной со своей собственной толпой продавцов воздуха. Каждый из этих всплесков породил огромную толпу мошенников и религиозных фанатиков, а также способствовал коррупции на факультетах информатики, где с начала 80-х годов, вероятно, её уровень стал довольно близок к коррупции экономических профессий с их группами высокооплачиваемых интеллектуальных [девушек с лёгким, как дуновение ветерка, поведением — правка автором сайта] или откровенных преступников, маскирующихся под профессоров.

Особенности языка

Исторически PL/1 был очень элегантной и инновационной смесью Фортрана, Кобола и Алгола-60 в одном языке, совместив все три основных нововведения в дизайне языков программирования того времени:

  • Удивительно гибкий и мощный набор управляющих операторов, включающий оператор if-then-else и три типа циклов: for-while-do. PL/1 был также первым языком, который представил возможность выхода из цикла с помощью одного оператора (позже унаследованного Cи, но с другим ключевым словом).
  • Схема выделения памяти трех уровней: статическая, автоматическая (через стек) и управляемая (через кучу), соединенная с отдельными атрибутами, которые определяют видимость (атрибут External предоставляет возможности, аналогичные общим блокам Фортрана).
  • Нетипизированные указатели с возможностью выполнения арифметических операций над ними с помощью функции unspec. Кроме того, класс BASED обеспечивает аккуратное обобщение указателей на структуры.
  • Обработчики исключений составляют особый тип сопрограмм. Они активируются, когда управление достигает оператора, и возобновляются при возникновении соответствующего исключения как события в программе. PL/1 поддерживает мощную обработку исключений и почти 30 лет (до появления C++) оставался единственным языком с таким мощным и гибким механизмом обработки исключений. Система исключений PL/1 была первой успешной попыткой ввести сопрограммы в язык высокого уровня. Одним из основных недостатков Cи (как производной от PL/1) было отсутствие исключений, которые сильно повлияли на написание программы для чтения файлов. Неспособность справиться с такими условиями, как OVERFLOW и ZERODIVIDE, была ещё одним важным недостатком. Исключение также можно использовать в PL/1 для проверки переполнения индексов в массивах (их можно включить выборочно для каждой процедуры/для каждого блока). Как это ни парадоксально, популярные современные языки, такие как C++ и Java, предоставляют гораздо худший механизм обработки исключений, чем PL/1.
  • Например, вы можете иметь отдельные обработчики для попыток делить на ноль, для обработки исчерпания входного файла, для обработки случаев, когда числа становятся слишком большими для полей в вашей программе и т.д.
  • PL/1 имеет возможность эмулировать множество исключений, чтобы программист мог проверить поведение программы. Любые исключения, которые вы не обрабатываете или которые не имеют своих собственных конкретных проверяемых условий, обрабатываются универсальным обработчиком системной библиотеки языка.

Обе эти функции значительно опередили свое время и усложнили компилятор. Это особенно верно в отношении исключений, которые, по сути, являются замороженными сопрограммами, и которые нужно активировать в контексте, отличном от контекста процедуры, в которой они содержатся. При этом нужно выделение памяти из кучи.

PL/1 был первым универсальным языком, который ввел исключения. Интересно отметить, что половина расширений C++, включая исключения, была связана с возможностями, которые создатели Cи удалили из PL/1 при создании своего языка :).

Интересно также отметить, что PL/1 был первым языком программирования, который обеспечивает правильную обработку такой распространенной проблемы, как обнаружение конца последовательного файла во время чтения. В PL/1 условие окончания файла «взводится», что активирует пока остановленную сопрограмму (обработчик исключений), в которой программист может делать все, что пожелает, но, как правило, просто переходит к первому оператору после цикла чтения. Такое использование goto определенно превосходит по понятности и эффективности ошибочные попытки выполнить эту проверку в заголовке цикла чтения, как это было сделано в Cи и Perl.

Я бы ещё раз обратил внимание следующие важные языковые особенности:

  • PL/1 — блочно-ориентированный язык в стиле Алгола. Программы могут выполняться отдельно и состоять из блоков исключений («замороженные» сопрограммы), обычных блоков, операторов и подпрограмм. Процедуры могут быть внутренними или составляться отдельно. Этот тип структуры позволяет программисту создавать высокомодульные приложения. Свободная форма без зарезервированных ключевых слов (последнее, вероятно, было ошибкой, которая усложняла компиляторы с нулевым возвратом инвестиций). Очень чистая лексическая структура. Разумное решение для закрытия нескольких блоков или групп операторов с одним разделителем. Это действительно забавно и трагично одновременно, что это важное средство все ещё отсутствует в Cи, C++ и Java; его отсутствие по-прежнему может генерировать кучу трудно находимых ошибок.
  • PL/1 был первым популярным языком со встроенным препроцессором. Эта функция была позже скопирована (и злоупотреблена) в Cи.
  • Очень аккуратное обобщение способности Фортрана использовать отдельно скомпилированные единицы компиляции. Оператор процесса и класс выделения внешней памяти.
  • Он определил типы данных для абстрактного обобщенного компьютера без учета фактического оборудования. PL/1 был первым языком общего назначения с пригодным для использования данных типа строка. Он также имеет объекты — битовые строки.
  • Один из первых языков общего назначения, в котором указатели являются встроенной функцией языка, а шаблоны, базированные на них, могут иметь произвольную структуру данных.
  • PL/1 содержал очень мощный набор управляющих структур, которые в некоторых отношениях остаются непревзойденными, и это намного превосходит то, что получил язык Cи (несмотря на то, что Cи является производным от PL/1). Из основных языков только Perl может конкурировать с PL/1 в части богатства и гибкости структур управления.
  • PL/1 поддерживает массивы, структуры, объединения, массивы структур или объединений, структуры или объединения массивов и любые их комбинации.
  • Концепция PL/1 «области» как способности выделять хранилище в конкретной области вместе с процедурами с несколькими входами была конструкцией, которая позволяет программирование в стиле ОО без типичных для ОО издержек.
  • PL/1 использовался в Multics в качестве языка системного программирования и был одной из первых попыток написать ОС на языке высокого уровня (эта попытка вдохновила Unix и Cи, в целом, на семантику и структуру подобную PL/1).
  • Компиляторы PL/1 находились на переднем крае разработки компиляторов благодаря оптимизирующему и отладочному компиляторам IBM, в течение многих лет они представляли лучшие образцы в своем классе. Компилятор PL/C (который был разработан в Корнуэлле и реализовал большое подмножество PL/1) был и остается одним из лучших компиляторов для образовательных целей, которые я когда-либо видел. Они по-прежнему выглядят потрясающе даже сейчас, спустя полвека после их первого выпуска, особенно в отношении качества диагностических сообщений.
  • Многозадачность была реализована уже в PL/1-F. Он содержал типы данных EVENT и TASK , опцию TASK в операторе CALL, WAIT-состояние, DELAY (задержка времени), опции EVENT в операторах ввода-вывода.

Важно отметить, что PL/1 использовался в качестве языка системного программирования для такой фундаментальной операционной системы, как Multics — создателя многих идей, которые впоследствии были переопределены в Unix. В частично «ублюдочном» виде ключевые идеи и большинство операторов PL/1 и семантику переменных можно найти в Cи, что, вероятно, следует рассматривать как косвенную производную и большое упрощение ядра PL/1.

Программы PL/1 состоят из блоков. Блок может быть либо подпрограммой, либо просто группой операторов. Блок PL/1 позволяет создавать высокомодульные приложения, поскольку блоки могут содержать объявления, которые определяют имена переменных и классы хранения. Таким образом, вы можете ограничить область видимости переменной одним блоком или группой блоков, или вы можете сделать это известным в модуле компиляции или в модуле загрузки.

Процедуры могут быть вложены, это очень простой и очень эффективный метод создания собственного пространства имен для набора процедур. Техника, которую любой программист может легко освоить и успешно применять. Так успешно, что обычно он/она уже никогда не писал по-другому с этого момента.

Как это ни парадоксально, PL/1 играл роль бесплатного программного обеспечения по крайней мере в одной стране ;-). И в СССР он быстро стал доминирующим языком программирования на мэйнфреймах, намного опередив Cobol и Fortran, которые все ещё доминировали на арене мэйнфреймов в США и других западных странах. Так что здесь аналогия с Perl выглядит ещё убедительнее. PL/1 доминировал, несмотря на тот факт, что советские клоны IBM 360/370 (называемые ЕС ЭВМ — русская аббревиатура «Единая Система компьютеров») были гораздо менее мощными (и гораздо менее надежными), чем западные аналоги.

И это все происходило в начале 60-х, а не в конце 80-х ;-).

Автор не известен. Переводчик и автор предисловия: Д.Ю.Караваев.

0

Автор публикации

не в сети 24 минуты

admin

3
Комментарии: 28Публикации: 173Регистрация: 13-06-2019
Авторизация
*
*

пять × 1 =

Регистрация
*
*
*

двенадцать − восемь =

Генерация пароля

2 × пять =

Перевести »
Прокрутить вверх
Scroll to Top