суббота, 22 января 2022 г.

Шеркало 05.09: (не)любимые системы программирования (Другие ч.3)

 - Шеркало, помолчи, я продолжаю про свои системы программирования! Потерпи, уже вроде бы немного осталось.

- Ладно, молчу, я покладистое. Что следующее7

PL/1

- А это що такое?

- Ой, Шеркало, ты будешь смеяться, может быть, но PL/1 - это такой Алгол-68, только разработанный фирмой IBM по своему вкусу. Оба языка создавались почти в одно и то же время (PL/1 вышел на несколько лет раньше, но в ту же эпоху). Их разработчики варились, можно сказать, в одном соусе, вдохновлялись одними и теми же идеями, в процессе разработки активно общались и спорили друг с другом. Разработчики Алгол-68 кричали:

- Ваш PL/1 похож на новогоднюю ёлку - понавешали на разные ветки разных ёлочных игрушек, и радуетесь, а если внимательно посмотреть, ваши игрушки друг к другу по цвету и форме не подходят!

- А ваш Алшол-68, - возражали IBMовцы, - вообще практически никому в нашем еловом лесу не интересен! Пусть у вас все игрушки на всех ветках одинаковой формы, зато, у нас есть пулемёт у нас есть настоящая работающая IBM/360, а у вас её нет!

- Интересно, на чьей стороне была правда, Ёж?

- На мой взгляд, как обычно, и там, и там, или, ни там, ни там. Что касается, новогодней ёлки, то да, это правда PL/1 можно было сравнить с ней. Но, чья бы корова, как говориться мычала, а вот корова разработчиков Алгол-68, лучше бы в данном контексте молчала. Разработчики нормальных компиляторов Алгол-68 столкнулись с не меньшими трудностями, чем разработчики компиляторов PL/1 - и там, и там были много-много-проходные реализации, с многолетней отладкой/доработкой/переделкой компиляторов, со стыдливыми комментариями о "проблемах оптимизации" кода, о "вынужденных ограничениях" на точность реализации ранних версий стандартов. Одно другого стоит.

В целом же PL/1 был совершенно нормальным и ожидаемым языком. У фирмы IBM были FORTRAN и COBOL, которые, хоть и работали успешно и добротно, но справедливо критиковались за тяжеловесность и устарелость технологий программирования. Был пример Алгола и порождённых им языков, с красивой, продвинутой блочной структурой и перспективой подхода к функциям и рекурсии. И, самое главное, на подходе была совершенно новая, прорывная система компьютеров IBM/360, для которой как воздух немедленно требовался новый, потрясающий всех язык высокого уровня!!! Ну вот взяли, всё самое лучшее, что смогли найти в тот момент, сложили в одну общую мусорную кучу. Скрестили вместе бульдога (Фортран) с носорогом (Кобол), и с ёжиком (Алгол), и ещё с несколькими семействами летучих насекомых, чтобы уж совсем красиво было. Вот и получился PL/1, вполне, кстати, добротный язык программирования. Программы выглядели примерно вот так:

Наверное, не самая лучшая иллюстрация программы PL/1 - та серединка, где в начале строк идут цифры "1, 2" - это описание структуры записей данных, хранящихся во внешнем файле, заимствованное в PL/1 целиком из Кобола, а больше в программе почти ничего интересного и нет. Но, и так сойдёт. Я вообще, о личном опыте собирался рассказывать.


PL/1 нам начали преподавать на первом курсе Университета. Дело в том, что практику по программированию в Университете мы тогда могли проходить только на ЕС ЭВМ (ЕС-1033 была, если не ошибаюсь, но могу путаться, там позже более мощную ЕС включили). Ну, а для ЕС ЭВМ (которая, как известно, совместима с IBM/360), ничего более подходящего, чем PL/1 быть и не могло. Я на нём какие-то там учебные программки тогда тоже вместе со всеми писал. А в конце первого курса меня, как одного из призёров университетской олимпиады (в первой десятке студентов, в конце первой десятки из всего трёх десятков участников, ага), отправили в Новосибирский Университет (НГУ) на региональный этап олимпиады по программированию. 

А в НГУ всё устроили "по взрослому". Олимпиада проходила целых два дня. Нужно было выполнить с десяток заданий разной сложности, за которые начислялось разное число баллов. Часть заданий была теоретическими - ответ на бумаге, а часть практическими - написать программу и получить результат её прогона на реальном компьютере. Во втором случае начислялся или полный балл, если результат правильный, или строго ноль баллов, при любой ошибке (разумеется, ставились ограничения на время написания программы и на число отладочных запусков). Ну и, поскольку олимпиада региональная, а программирование везде преподавали по-разному, нам давали возможность выбрать язык программирования. Я взял, и выбрал свой любимый Паскаль. А все остальные студенты (из реально серьёзных претендентов на победу, не считая всяких деревенских маргиналов, второй раз в жизни клавиатуру увидавших), включая абсолютно всех новосибирцев, и всех томичей, кроме меня, выбрали PL/1. Потому что только на PL/1 и только для серьёзной ЕС ЭВМ и пишутся НАСТОЯЩИЕ серьёзные программы. А остальное - для лохов и сосунков.

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

Задача была очень простая, даже "детская". Программе на вход давалось множество точек на плоскости, каждая точка определялась парой координат (X, Y). И задавалась окружность с центром (X0, Y0) и радиусом R. Нужно было определить, сколько точек из заданного множества лежит внутри окружности, а сколько - снаружи. Всё было бы совершенно элементарно, если бы не один мааааленький подвох. В олимпиадном тесте количество точек внутри окружности превышало 40000 штук (т.е. 16-разрядного целого числа было недостаточно для их подсчёта).

У меня с Паскалем никаких проблем не возникло - компилятор работал на 32-разрядной ЕС ЭВМ, поэтому по умолчанию отвёл под счётчик точек переменную в 32 разряда. Этого с запасом хватило. А вот в PL/1 всё оказалось иначе. Там целые переменные по хорошему нужно описывать с явным указанием точности (это же одна из важных особенностей языка, делающая его воистину "профессиональным" - чтобы программист каждую спичечную головку, каждую копеечку, сам вручную к нужному месту присобачивал). В PL/1 переменную счётчика нужно было описать примерно так:

DCL  COUNT  FIXED BINARY(15);  /* целое 16 разрядов */

или так:

DCL  COUNT  FIXED BINARY(31);  /* целое 32 разряда */

а можно было написать и вот так:

DCL  COUNT  FIXED BINARY;  /* без явного указания точности */

но в последнем случае, компилятор сам про себя решал, что нужно взять самую короткую переменную (16 разрядов), чтобы сэкономить память. Так вот 100% студентов, писавших тогда в НГУ эту программу на PL/1 использовали либо первый вариант (потому что так писали в учебном классе - там память тоже учили по возможности максимально экономить), либо третий вариант (потому что вообще о точности не задумывались), и получали в результате целочисленное переполнение и отрицательное количество точек в круге, в ответе задачи. В итоге, я со своим маргинальным Паскалем оказался вообще единственным, кто правильно решил эту задачу! Оказалось, что для правильного результата мало выбрать "профессиональный" инструмент, нужно ещё и уметь его правильно профессионально использовать.

Ну а мой личный путь с PL/1 после Университета больше никогда не пересекался. Язык, как я уже сказал, получился достаточно добротный, хотя и сильно старомодный (переусложнённый синтаксис при отсутствии многих важных современным возможностей), но нигде кроме больших ЕС ЭВМ, у нас этого монстра никогда не использовали, а ЕС уже в начале 1990-х очень быстро вышли из употребления. Дальше PL/1 уже мало кого интересовал.


Язык Си.
- Ёж извини, что прерываю. А вот, мне кажется, или ты специально обходишь стороной, такой известный язык, как Си? Ведь, вроде бы, всё самое серьёзное, только якобы на нём и написано? А ты, всё сторонкой, сторонкой. да всё мимо...
- Си? Добро, Шеркало, замолвлю слово и за него. Утверждения, что "всё самое-самое только на Си", это конечно бред. С другой стороны - действительно ЭПОХАЛЬНЫЙ язык, без всяких шуток. в значительной степени повлиявший на синтаксис многих более современных языков, и что важнее, на развитие (как в положительном, так и в отрицательном смысле) современных парадигм программирования. А вот лично у меня с Си, в самом деле, к сожалению, интимные отношения не сложились. Мы с Си не пересеклись в нужном месте и в нужное время, а когда в итоге всё-таки пересеклись, то времена для влюблённостей уже миновали.

Затруднюсь выбрать пример короткой программы на Си. Разве, что уж совсем примитивный? Впрочем, это не имеет значения, сишные программы внешне выглядят всё равно, как почти любые современные программы. Ну, вот так пойдёт?

#include <stdio.h>

float power(float x, int n) 

  int ifloat s;

  s=1;

  for (i=0; i<n; i++) s=s*x;

  return s;

} 

int main() {

  float y;

  y=power(2.125,10);

  printf("Result: %f\n",y);

  return 0;

}


"Не сложилось" у меня с Си очень просто. В школьный период, когда я начал знакомиться с Си, он мне был весьма интересен, но вот попробовать запустить сишную программу я в ИОА тогда не мог - ни на БЭСМ-6, ни на М4030, доступных мне рабочих трансляторов Си тогда там не было. Изучать Си чисто теоретически "на бумаге" - вовсе неинтересно, это просто потомок уже известного Алгола, структурный и процедурный, что там такого особенного можно без доступа к компьютеру увидеть? В результате, я очередной раз прочитал очередную "умную книжку" про Си, принял её к сведению, временно забыл.

На практике Си стал мне доступен только в начале 1990-х, как в ИОА, так и в Университете, сначала на клонах архитектуры DEC PDP/VAX-11 (СМ ЭВМ, "Электроника", ДВК и т.п.), чуть позже на персональных компьютерах ПК (клонах IBM PC). Конечно же, я попытался к Си повторно приобщиться, ведь все программисты только о нём и говорят! И вот тут сработали два других негативных (с точки зрения любви к Си негативных) фактора:

1. К тому времени я уже хорошо знал ассемблер PDP-11, активно программировал на нём (БК-0010/0011(М)). И мне было абсолютно очевидно, что "знаменитый" язык Си - на самом деле всего лишь примитивная надстройка над ассемблером! Просто способ записать ассемблерный код PDP-11 в чуть более краткой форме, внешне напоминающей алгол-структурированную программу. Можно сказать, макро-язык поверх ассемблера. Сколь-нибудь опытный программист PDP-11 (я таким уже немножко тогда был) совершенно спокойно, прямо на невооружённый глаз, раскладывал любую программу на Си прямо в уме на ассемблерные команды: вот здесь будет такой комплекс команд, здесь вот такие условные и безусловные переходы, здесь вот такие режимы обращения к памяти и регистрам, автоинкременты, декременты не забываем здесь вот так вот задействуем стек. Всё, сделано, нафига тут нужен был какой-то Си?!
Опытный программист PDP-11 вообще в языке Си не нуждался! Это правда  Я сам лично был свидетелем! Ой! Чёрт! А Керниган? А он-то почему туда пош...?

2. Известно, почему. Там не только Керниган, там целая стая академиков подпевала! Говорили, что в результате анализа, стало известно, что 
а) итоговый машинный код программы на Си всего лишь на 5-10 % больше, чем код той же самой программы, написанной на ассемблере. Но вот, 
б) программа на Си содержит в 5-10 раз меньше строк, чем аналогичная ассемблерная программа. А психологи, с свою очередь, говорят, что 
ц) программист за один день может написать не больше 200 разумных строк (в среднем), абсолютно не важно, на каком языке.
Сопоставляем факты а) б) ц), и получаем очевидный (якобы) вывод - Писать программы на языке Си в 10 раз эффективнее, чем писать их на ассемблере. Очевидно же?! Количество строк в сутки = константа. Программа на Си занимает в 10 раз меньше строк, чем почти такая же программа на ассемблере. Вывод - писать программы на Си = в 10 раз эффективнее! В сутки средний программист может написать на Си в 10 раз больше кода, чем тот же программист на ассемблере! УРА!!! Все пишем программы на Си!!! Да? Что не так? 

Возражение очень простое: программист, он ведь не машинистка, которая тупо фигачит под диктовку по 200 нажатий клавиш на пишущей машинке в минуту, не разбирая, что она там фактически печатает. Программист обязан прежде всего думать над тем, что пишет. А количество строк - абсолютно вторично. А вот время и эффективность размышлений программиста, они никак в количествах строк в сутки не измеряются. И напротив, когда дойдёт время до записи текста итоговой программы в строках, там время на их набор займёт едва ли один процент от общего времени разработки программы, независимо от количества строк. Так стоило ли экономить на спичках?

3. Вернёмся от PDP-11 к более современным персональным компьютерам ПК. Там- то что меня в языке Си не устроило? Как ни смешно, ответ - язык Паскаль (о, моя любовь!) и фирма Борланд. :))
Дело в том, что та самая фирма Борланд, в раннюю эпоху развития компьютеров ПК (IBM PC) писала целые линейки разнообразных компиляторов с разных языков программирования. Эти компиляторы обычно выпускались по маркой "Turbo", при этом, несмотря на жутко самохвалебное название, трансляторы реально были продвинутыми и востребованными, на момент их выпуска. В линейке "Turbo" были и "Turbo Basic", и "Turbo C", и "Turbo Prolog", и "Turbo Pascal"... Ах. "Turbo Assembler", тоже. конечно был. Я не возьмусь сказать, всю ли начальную линейку компиляторов фирмы Борланд я перечислил? Наверняка, нет, простите меня, если чего забыл!.
Для меня, в начале 1990-х стоял выбор, между "Turbo C" и "Turbo Pascal". Си, тогда, в момент начала 1990-х годов проиграл Паскалю мой личный тендер с абсолютно разгромным счётом, почти всухую! Проиграл по той же самой причине. по которой я когда-то ранее отверг Алгол-60: 
просто на Паскале всё было линейно и ясно, а на Си, как и ранее на Алголе, приходилось путаться на ровном месте. Си - слишком краткий (он сознательно таким сделан, чтобы писать максимально полезные программы на компьютерах с минимально доступной памятью). Но из-за этой краткости (и адресной арифметики вкупе с неявными преобразованиями типов) в Си очень легко случайно ошибиться, и очень сложно потом найти свою собственную ошибку (а не дай чёрт, программу писали сразу несколько человек, и тебе лично выпала доля найти ЧУЖУЮ ошибку, вот он, где настоящий АД!!!)

В итоге, Шеркало, как раз к тому времени, как я дорос до настоящего понимания языка Си, и до готовности его всей душой принять, оказалось, что я тогда же из этого языка и вырос. Он стал мне слишком маленьким, неудобным для сколь-нибудь больших приложений, и одновременно слишком тяжеловесным, жёстким для сколь-нибудь реально маленьких приложений. Ни туды, ни сюды. Где такое применить? Ах, да, его в ранних версиях UNIX с успехом применяли... Так и что с этим фактом мне сейчас делать? Да ничего... Остался на Fox и Pascal. Был бы вынужден перейти на Си, если бы работал в коллективе, где это обязательный стандарт, но не пришлось.

Комментариев нет:

Отправить комментарий