В институте в одной группе с нами учился парнишка, сын сотрудников советского посольства, который родился и первые четырнадцать лет жизни прожил в Лондоне. Учился он в местной школе. Когда пришло время в институте сдавать экзамен по английскому языку, он получил тройку. Факт показался настолько невероятным, что от группы были выбраны делегаты и отправлены на кафедру иностранных языков.
- Как это могло случиться, - спросили мы у заведующей кафедрой, - ведь он же родился в Англии и английский язык для него почти родной?
- А мы и не сомневаемся в том, что он знает английский язык, но он не знает грамматики.
- Как же может не знать грамматику английского языка человек, который несколько лет подряд проучился в английской школе? - удивились мы.
- Ничего странного в этом нет, - ответила заведующая, - у них там своя грамматика английского языка, а у нас своя.
Остается добавить, что диалог этот происходил в середине 50-х годов.
Подобный диалог не вызвал бы никакого удивления, если бы речь шла не о грамматике английского языка, а о грамматике какого-либо из алгоритмических языков, на которых программист общается с ЭВМ. У английского языка одна грамматика и никакой другой быть не может. А вот у одного и того же алгоритмического языка грамматик может быть много. Придумали даже классы грамматик. Но ничего хорошего в этом нет. Как, впрочем, ничего хорошего нет и в алгоритмических языках. Появились они в период младенчества ЭВМ, и по мере возмужания ЭВМ постепенно переходят на общение средствами обычных человеческих языков. Путь этот достаточно сложен.
Как это делает человек?
Поставьте себя на место человека, выполняющего какую-нибудь сложную работу, например конструирующего новый самолет. Мы не в состоянии углубиться в подробности его творческой кухни, для этого понадобились бы тома специальных изданий. Пробежимся, так сказать, по верхам, останавливаясь на некоторых, основных, на наш взгляд, деталях. Добавим к тому же, что сами мы не авиаконструкторы, поэтому наверняка в чем-нибудь и ошибемся.
Первый этап нам представляется так. Человек воображает себе и, наверное, набрасывает на бумаге контуры, общую компоновку будущего самолета. Важно отдать себе отчет, как он это делает. Прежде всего за основу берется некоторый обобщенный образ самолета, пока еще лишенный или почти лишенный индивидуальных черт. Стоп! Вот это чрезвычайно существенно.
Обобщенный образ самолета берется готовый - извне, неважно откуда. Он уже существует к моменту начала проектирования. Далее в обобщенный образ вносятся изменения. Какие? Они могут быть радикальными и небольшими. Можно добавить еще пару крыльев, превратив моноплан в биплан, а можно немножко изменить обводы фюзеляжа. Так или иначе, но на этом этапе процесс конструирования сводится к определенной схеме. Вносятся изменения, и то, что получилось, испытывается на соответствие определенным критериям. По результатам испытаний изменение либо принимается, либо не принимается.
Как это делает человек?
Критерии бывают самыми различными. Опытный конструктор, вообще говоря, представляет, как поведет себя та или иная форма в воздухе. Он может представлять себе или точно, или приближенно, или, наконец, неверно. Он может представлять себе это подсознательно. В числе прочих критериев могут быть критерии чисто эстетические. Тем не менее рассматриваемый этап сводится к знаменитому методу проб и ошибок. Часто говорят, и совершенно правильно, что на этом этапе ставится мысленный эксперимент. В результате рождается конструкция первого приближения.
Что для нас важно? Во всем описанном процессе при выполнении его человеком самой дефицитной оказывается фантазия. Да что говорить о конструкторах! Фантасты-литераторы, для которых фантазия, казалось бы, является основным инструментом, основным средством производства, не дали нам ничего, кроме нескольких достаточно примитивных приемов. Попытаемся перечислить главные из них.
Все то же самое, но изменяется количественно: Гулливер и лилипуты, из пушки на Луну.
Какая-нибудь деталь или несколько деталей добавляется или отбрасывается: человек с тремя ногами или одним глазом.
Известное - в необычной среде: ковер-самолет, подводная лодка.
Полное отрицание. Это, пожалуй, самый сильный и в то же время хуже всего удающийся человеку прием. В качестве примера здесь можно назвать человека-невидимку, людей, вообще лишенных тела (ангелы), попытки воспроизвести течение жизни при скоростях, больших скорости света, в условиях гравитационного коллапса и т. п.
Весьма интересная подробность. Свидетельства на изобретения, то есть документы, основная задача которых зафиксировать появление чего-то нового, содержат так называемую "формулу изобретения". Как и положено всякой формуле, она пишется по раз навсегда принятому стандарту. Вначале описывается нечто известное, существующее, иначе говоря, прототип. Затем вразрядку пишутся два сакраментальных слова: "отличающееся (щийся, щаяся) тем..." Далее следует перечень отличий, который характеризует данное изобретение.
Если угодно, можно предложить нечто вроде формулы творчества, то есть свести процесс творчества к следующим этапам. Во-первых, выбор прототипа. Во-вторых, внесение в прототип изменений, проверяемых каждый раз на соответствие некоторым критериям. Этот этап, в свою очередь, разбивается на несколько стадий.
Мы рассмотрели одну из них, назвав ее мысленным экспериментом. За ней следуют стадии строгих количественных расчетов, изготовления и испытания макетов, опытного образца и т. п. Результатом чаще всего оказывается необходимость начать все сначала, поскольку на одном из этапов обнаруживается несоответствие того, что получилось, существующей системе критериев. Однако в конце концов процесс может завершиться успехом.
Что она может?
Ну а ЭВМ? Можно ли хотя бы мечтать о том, чтобы поручить ЭВМ выполнять самостоятельно хотя бы одну из перечисленных стадий? Так вот, чтобы в дальнейшем не было никаких неясностей, заявим сразу: мы глубоко убеждены в том, что ЭВМ способна, и притом вполне самостоятельно, выполнять любую из перечисленных стадий, а также и все их, вместе взятые. Лучше всего должна удаваться ЭВМ стадия мысленного эксперимента.
В чем здесь дело? Человек мыслит медленно, и память его ограниченна. Только люди, обладающие феноменальными способностями, могут выполнять в уме довольно сложные вычисления, да и то они ограничиваются обычной арифметикой. Поэтому в процессе мысленного моделирования человек способен прикидочно оценить потенциальные свойства той или иной конфигурации. В дальнейшем, как уже говорилось, она должна быть подвергнута более точному расчету, чаще всего с помощью той же ЭВМ.
ЭВМ в меньшей степени страдает от подобных ограничений. В силу своего чрезвычайно высокого быстродействия она способна уже на первой стадии просмотра вариантов проводить довольно глубокие оценки и сразу отбрасывать то, что при работе человека было бы отброшено на гораздо более поздних стадиях. В какой-то степени ЭВМ способна заменять и физический эксперимент, если она снабжена хорошим математическим описанием физических процессов, чего пока ей в основном и не хватает.
ЭВМ способна, если это необходимо, потребовать выполнения физического эксперимента, спланировать его и изготовить рабочие чертежи опытной установки. Совместно с группой роботов, о них речь еще пойдет впереди, ЭВМ способна выполнить и физические эксперименты.
Вряд ли надо добавлять, что обычные технические расчеты ЭВМ тоже способна выполнить, равно как и изготовление чертежей. Еще одна работа, сейчас уже традиционно поручаемая ЭВМ, это обработка результатов эксперимента.
Наши размышления хотелось бы закончить следующим соображением. Если при обсуждении конструкции мы находили и подчеркивали довольно много отличий у искусственных систем при сравнении их с естественными, то работа ЭВМ практически почти не отличается от того, как в аналогичных условиях работает человек.
Младенцы
Так что, можно закрывать авиационные, а заодно и прочие конструкторские бюро? Нет, наверное, стоит еще некоторое время подождать. Ведь мы с вами рассмотрели, что могут делать ЭВМ, но мочь еще не значит делать. Ведь то же самое и у нас с вами. В принципе каждый человек может быть хорошим конструктором, Нo ведь, поди ж ты, из кого-то получается конструктор, а кто-то так всю жизнь и работает сторожем.
Очень важно и другое обстоятельство. Чтобы человек стал хоть каким-нибудь конструктором, его учат. Учат чуть ли не половину всей его жизни. С ЭВМ получилось иначе. Поначалу мы не стали их учить. Вместо этого сразу же заставили работать, можно сказать, в младенческом возрасте. К тому были свои причины: и объем памяти у ЭВМ первого поколения был еще недостаточно большим, чтобы говорить о каком-то обучении, и работы для них накопилось уж очень много, и, самое главное, то, что никакого опыта в воспитании ЭВМ у нас тогда еще не было. Вот и заставили работать младенцев, можно сказать, еще в родильном доме.
Но в том-то вся беда, что точно так же, как человеческий младенец потенциально может многое, но объяснить ему, что надо делать, не так-то просто, так же и необученная ЭВМ не понимает, что надо делать. Поэтому на первых порах к ЭВМ приставили нянек - тех самых семерых нянек, у которых дитя без глаза. Няньки имели разные профессии, из которых самыми массовыми оказались две. Первая - программисты, вторая - алгоритмисты.
Новорожденный младенец гукает, тянет в рот что ни попало, охотнее всего пальцы ног. Это своеобразный язык, на котором он общается с внешним миром. С младенцами все ясно. Их сначала учат говорить и понимать сказанное, а затем требуют, чтобы они выполняли те или иные указания. С ЭВМ решили поступить наоборот. Окружили их специальными няньками-программистами, которые общались с ЭВМ "гуканьем" и при этом страшно гордились собой, а профессия программиста в течение долгого времени считалась весьма почетной и дефицитной.
Чтобы рассуждать конкретнее, рассмотрим какой-нибудь пример. Признаемся честно, выбор примера в данном случае представляет большие трудности. Действительно, возьмем, например, игру в шахматы. Кто-нибудь из читателей обязательно скажет, мол, игра она и есть игра, а нас интересуют серьезные дела. Выберем писание стихов или музыки - опять у читателя наготове возражения, что таких стихов, как Евтушенко, ЭВМ все равно не напишет, а значит, и говорить не о чем. А как доказать, что эти стихи лучше, а те хуже? Если честно, то сегодня этого никто не знает. Наконец, возьмем так широко распространенный сегодня станок с числовым программным управлением. Опять слышен голос оппонента:
- Управлять станком - это же не творческая работа!
Вот и получается, что примеров много, а выбрать не из чего. Но поскольку пример все-таки нужен, давайте все вместе, включая ЭВМ, попробуем отыскать путь в лабиринте. Заодно научимся программировать.
Первая премудрость, которую надо усвоить (мы о ней в предыдущей беседе упоминали), - это то, что каждое действие ЭВМ выполняется по команде, команды пронумерованы и, если нет других указаний, выполняются в порядке своих номеров. Точно так же, как в обычной очереди. Подобный порядок выполнения команд называется их естественной последовательностью. Выполнение команд в их естественной последовательности (если, еще раз повторяем, нет других указаний) можно назвать основным законом функционирования ЭВМ.
Ну а теперь в путь по лабиринту. Раз-два, раз-два, левой-правой, левой-правой! Первая команда, вторая команда, третья команда, четвертая команда, топ-топ, топ-топ! Да простит нам читатель это сюсюканье - не забывайте, что мы имеем дело с новорожденной ЭВМ.
Младенцы
Движемся по коридору лабиринта. Искушенный читатель мог бы сделать здесь и, наверное, сделает по меньшей мере два возражения. Первое, по его мнению, это то, что двигаться по плоскости (считаем лабиринт плоским) - это значит каждый раз вычислять координаты очередной точки. Следовательно, машина все-таки вычислительная? Все в конечном итоге сводится к вычислениям?
Ничего подобного! С той же легкостью, как с арифметическими операциями, машина оперирует и с отношениями, в частности с отношениями смежности. В таких условиях двигаться - это значит освобождать некоторый элемент площади (записывать в него нуль, если раньше была записана единица) и занимать соседний, смежный, элемент - заменять в нем нуль на единицу. Что такое "соседний", машина, как мы только что сказали, знает.
Второе возражение более серьезное. К чему оно сводится? По условию, движение совершается в лабиринте и перешагивать через стенки нельзя. Поэтому каждый шаг представляет собой не элементарное действие, а целую последовательность действий такого типа: ткнулись направо - уперлись в стенку, изменили направление движения - снова уперлись в стенку и так далее, пока впереди не обнаруживается свободное пространство и можно делать шаг.
Топ-топ, левой-правой! Выполняется естественная последовательность команд. Но вот обнаруживается разветвление коридоров. По какому из двух путей продолжать движение? Для выбора есть много способов.
Простейший - всегда поворачивать, например, только вправо. Точнее, в самый правый из нескольких коридоров при условии, что он уже однажды не был пройден.
Можно бросить монету. Да-да, бросить монету! Иначе говоря, совершить случайный выбор. Случайный выбор машина умеет делать гораздо лучше человека, и это подтверждается тем, что в орел и решку машина у человека всегда выигрывает.
Можно вычислить вероятность успеха для каждого из путей.
Наконец, можно заглянуть в память (машинную, конечно) и воспользоваться предыдущим опытом.
Но что важно? Все сказанное не имеет никакого отношения к программированию. Программист должен знать одно: попадая в точку разветвления, машина должна выбрать путь. Как она будет это делать, относится не к программе, а к существу задачи. Попутно выполняется небольшая проверка. Не достигнут ли конец лабиринта? Если достигнут, то машина, ликуя, сообщает о выполнении задания, если нет, она возвращается в исходную точку программы и все начинается сначала: топ-топ, левой-правой...
Вот и вся премудрость. Давайте рассмотрим внимательно рисунок 8. Начнем с самого верха, где написано: "Вход в программу". Логичнее было бы написать "начало", но дело в том, что относительно каждой программы трудно определить, где у нее начало. Каждая программа может быть частью другой, более сложной. Слова "Вход в программу" и означают, что, начиная с определенного момента, действует именно эта программа. Кроме того, здесь возможно выполнение некоторых вспомогательных действий, которые на данном уровне рассмотрения несущественны.
Рис. 8. Программирование
Вошли в программу. Минуем пока прямоугольник, на котором написано "Модификация", и обращаемся к прямоугольнику "Тело программы", Тело программы - это и есть цепочка команд, выполняемых в их естественной последовательности. Какие это команды, совершенно безразлично. Потому мы и выбрали в качестве примера отыскание пути в лабиринте, что эта задача напоминает другие, подчас гораздо более серьезные, например решение вопроса о том, увольнять или не увольнять некоторого сотрудника.
Тело программы предусматривает, кроме команд, наличие операндов, то есть объектов, над которыми выполняются команды. Операндом может быть все, что угодно. В нашем случае это элементы площади коридоров с пометками о том, заняты они или свободны, были однажды пройдены или нет. Каждый такой элемент содержит в себе список соседних элементов. Но все это не имеет никакого отношения к программированию. Программисту достаточно знать, что операнды существуют. Операнды, как и команды, нумеруются по порядку, причем порядковый номер операнда называется его адресом. В состав каждой команды входит адрес соответствующего операнда.
Дойдя до конца естественной последовательности, переходим в следующий прямоугольник, обозначенный как "Формулирование условий". Здесь происходит следующее. Последовательно, позиция за позицией, просматривается список элементов площади, смежных с данным. Возможны три случая. Во-первых, в списке оказывается лишь один смежный элемент, причем этот единственный элемент либо уже пройден, либо еще не пройден. Во-вторых, в списке имеются два или более смежных элементов. В-третьих, единственный смежный элемент оказывается выходом из лабиринта.
При всех условиях из прямоугольника "Формулирование условий" мы переходим в ромб, на котором написано: "Принятие решения" (почему ромб, мы не знаем - такова общепринятая символика у программистов). В нашем случае ромб эквивалентен вопросу: является ли смежный элемент выходом из лабиринта? Если ответ положительный (на рис. 10 так и написано, "да"), работа программы заканчивается.
Если ответ отрицательный, осуществляется возврат в начало программы. Тогда-то и вводится в действие группа команд, обозначенная прямоугольником с надписью: "Модификация". Что делается в случае, когда обнаружены разветвления? Об этом мы говорили. Чтобы реализовать каждый из способов (например, бросить монетку), может понадобиться своя, достаточно сложная программа. Наконец, остается случай, когда единственный смежный элемент уже пройден, то есть мы зашли в тупик. Первоначально выбранный путь оказался неверным, и все надо начинать сначала. С какой точки начинать? Это опять-таки предмет для серьезных рассуждений, но лежащих за пределами обязанностей программиста.
Что должен уметь программист? Строить схемы, аналогичные показанной на рисунке 8. Иначе говоря, он должен построить естественную последовательность команд и снабдить ее в нужных местах средствами формулирования и проверки условий. В зависимости от того, что происходит с условиями, естественная последовательность может быть нарушена. Для этой цели каждая машина снабжается специальной командой или группой команд, которые называются командами перехода или командами нарушения последовательности.
Программист должен уметь производить модификацию, для чего над командами и операндами выполняются специальные операции. В нашем случае, к примеру, если обнаружен тупик, то в команду номер 1, означающую начало движения, следует подставить адрес элемента коридора, с которого решено продолжать поиск. Хранение команд наряду с операндами в памяти ЭВМ и возможность выполнения операций над командами точно так же, как и над операндами, это второй основной закон работы ЭВМ.
Что нам осталось добавить к сказанному? Изображенная на рисунке 8 и столь подробно рассмотренная последовательность действий называется циклом. Цикл может входить внутрь программы или внутрь прямоугольника (программисты говорят, блока), помеченного словом "Модификация". В случае бросания монеты, то есть образования случайного числа, выполняется программа, наверняка имеющая вид цикла. Подобная ситуация получила название цикла в цикле или вложенных циклов. Любая серьезная программа представляет собой очень много циклов, вложенных друг в друга.
Вот и вся премудрость! Пусть читатель рассудит сам. Неужели здесь есть нечто такое, чему нельзя было бы научиться, если не за день, то хотя бы за неделю? Топ-топ, топ-топ... Стоп - разветвление. Куда? Направо. И снова топ-топ... Недаром оказалось, что лучшими программистами являются школьники младших классов. Наверное, потому, что у них нет предрассудков, а все только что описанное очень напоминает игру.
В мире сейчас работают около миллиона программистов. Работают с полной отдачей сил, и еще примерно десять лет тому назад считалось нормой, если программист писал в день около трех команд. Конечно, имеются в виду команды, вошедшие в окончательный текст программы после выполнения весьма трудоемкой и порядком-таки нудной процедуры, называемой отладкой.
В чем же дело, если все так просто? Дело в том, что мало-мальски сложная программа, имеющая практическое значение, содержит десятки, а то и сотни тысяч команд. Человеку свойственно ошибаться, и как раз при написании программ это свойство проявляется в наибольшей степени. Все команды похожи друг на друга, не за что, как говорится, зацепиться глазу, ошибки здесь неизбежны. А вот отыскать ошибку - задача на редкость трудная. Для этого, грубо говоря, нужно кропотливо проделать все то, что по этой программе должна делать ЭВМ. Но ЭВМ выполняет миллионы операций в секунду, а программист на такую скорость не способен. Специально для отладки в ЭВМ ввели пошаговый режим, когда в результате нажатия кнопки машина выполняет одну-единственную команду и сообщает результат программисту.
Но и это еще не все. Тому, кто хоть однажды бродил в настоящем лабиринте, хорошо понятно, как легко попасть в так называемый порочный круг, то есть снова и снова ходить по одним и тем же коридорам. Такая же опасность поджидает и программиста. Обнаружить порочный круг среди сотен тысяч команд - задача архисложная, вот почему и получалось всего три команды за день напряженной работы.
Но отсюда же и ярчайший парадокс, связанный с развитием информатики. Надеемся, что мы дали читателю достаточно данных для того, чтобы к тем же выводам он пришел самостоятельно. Научиться программировать очень просто. Здесь нет ничего такого, что требовало бы какой-то серьезной подготовки или изощренной работы ума. Трудно не сделать ошибки. И еще труднее сделанную ошибку обнаружить. В том-то и парадокс.
Если ЭВМ что-то особенное умеет - она умеет не ошибаться. Современная ЭВМ четвертого поколения работает без единого сбоя, скажем, месяц по двадцать четыре часа в сутки и выполняет за это время, повторяем, без единой ошибки 2,5·1012, то есть два с половиной триллиона, операций. Почему же это замечательное свойство ЭВМ не использовали с самого начала?
На пути к возмужанию
Так все выглядит теперь, поскольку говорили мы о младенчестве ЭВМ, об их первом поколении. Причина столь жесткой опеки ЭВМ со стороны программиста заключалась в основном в характеристиках самих ЭВМ. Быстродействие было настолько мало (порядка тысячи операций в секунду против современных миллиардов), а память настолько ничтожна, что желать чего-то большего было бы явно неоправданно.
Глядя с позиций сегодняшнего дня, нельзя закрывать глаза и на другую причину, которая, несомненно, влияла на развитие и применение вычислительной техники. В чем она состояла? Общественное мнение, которое разделялось и специалистами, утверждало безапелляционно: ЭВМ способна лишь слепо выполнять введенную в нее программу. Все, что касается программирования, есть прерогатива человека. Мнение это повторялось на разные лады и в технической и в художественной литературе. Конечно, в таких условиях трудно было отойти от принятых шаблонов.
Как шло дальнейшее возмужание ЭВМ? Вначале (совсем по Библии) было слово, точнее, появились языки. Их назвали алгоритмическими. Основным в каждом машинном языке стало понятие идентификатора, то есть произвольного сочетания букв и цифр. Идентификаторы использовались как имена операндов (говоря высоким "штилем"), а попросту говоря, каждый идентификатор представлял собой условное обозначение ячейки памяти, в которой хранится данный операнд. Тем самым ЭВМ доверили сложнейшую задачу - выписать из программы все идентификаторы, расположить их в любом удобном для нее порядке, а затем присвоить им порядковые номера, которые одновременно (как и в доязычный период) служили адресами ячеек. Если в данной ячейке памяти предполагалось хранить не операнд, а команду, то соответствующий идентификатор получал название не идентификатора, а метки.
Следующей языковой единицей стало так называемое выражение. Это не что иное, как цепочка команд, в которой ни при каких условиях не нарушается естественная последовательность. В подавляющем большинстве языков допускалось использование лишь арифметических и логических выражений (упорно считалось, что машина должна только вычислять). Поэтому в выражении команды записывались в виде знаков, общепринятых для обозначения соответствующего арифметического или логического действия. Например, "+" для сложения или "V" для логической операции ИЛИ.
Машине оказали огромное доверие выбрать из выражения все знаки, обозначающие операции, расположить их в нужном порядке и связать соответствующими операндами. Выражению в языках присваивался смысл числа или значения соответствующей логической переменной. Иначе говоря, с позиции языка предполагалось, что все входящие в выражение операции уже выполнены и результат подсчитан.
Следующую группу языковых единиц составляли операторы. Что они представляют собой? Лучше всего показать это на примере простейшего из них - оператора присваивания. Смысл оператора присваивания состоит в том, что данному идентификатору присваивается некоторое значение, например, значение какого-то арифметического выражения. Все это опять-таки говоря высоким "штилем", а по-простому означает, что нужное значение записывается в ячейку памяти, обозначаемую данным индентификатором.
Кроме оператора присваивания, практически в каждом языке (общее число их, мы забыли об этом сказать раньше, давно перевалило за тысячу) встречаются еще три оператора. Оператор перехода просто предписывает, начиная с определенного момента, переходить к выполнению фрагмента программы, помеченного меткой, входящей в состав этого оператора.
Оператор цикла заслуживает того, чтобы остановиться на нем подробнее. С небольшими изменениями грамматическая форма оператора цикла имеет вид:
FOR С STEP D UNTIL Е DO.
Здесь: FOR - это слово, говорящее о том, что мы имеем дело с оператором цикла. Далее (мы обозначили этот фрагмент буквой С) перечисляется условие входа в цикл. Это может быть простейшая запись х=1. Она означает, что программа начинает выполняться при значении переменной х, равном единице. Затем следует слово STEP, указывающее на то, что за ним в той или иной форме заданы условия модификации (у нас эти условия обозначены как D). В простейшем случае запись STEP 1 означает, что после очередного возврата к началу цикла значение переменной х увеличивается на единицу.
Наконец, слово UNTIL указывает на то, что за ним формулируются условия окончания. Например, UNTIL х<100 означает, что обходы циклов продолжаются до тех пор, пока значение переменной х остается меньше ста. Само тело программы записывается после только что разобранной строки.
Снова, в который раз, хочется задать вопрос: только и всего? Но все усугубляется еще одним интересным обстоятельством. Сравните нашу строку с рисунком 8. Конечно, это одно и то же. Только на рисунке надо заполнить содержанием пустые геометрические фигуры (прямоугольники и ромб), а в языковой конструкции - заполнить тем же самым содержанием пробелы между словами FOR и STEP, UNTIL и DO. Оператор цикла представляет собой некий формализм. Чем заставлять программистов заучивать правила его образования, можно было сразу поручить все это делать ЭВМ.
Последний из упомянутых трех операторов - условный - имеет вид:
IF С THEN A ELSE В,
что читается (в том числе и ЭВМ) так: если условие С удовлетворяется, переходи к выполнению фрагмента программы А, в противном случае переходи к выполнению фрагмента программы В.
Человек, хорошо усвоивший все сказанное, с полным основанием может считать, что он овладел соответствующим языком программирования. Не сомневаемся, что подобное утверждение встретит яростное возражение со стороны профессионалов-программистов, но тем не менее это так. С помощью выражений и перечисленных операторов можно составить любую, без каких-либо исключений, программу. Это не частное мнение авторов данной книги, а строго доказанный факт, представляющий собой содержание знаменитой теоремы академика В. Глушкова.
Иное дело, что каждый конкретный язык предоставляет программисту некоторые дополнительные удобства. Как правило, имеются средства, позволяющие систематизировать операнды, оформив их в виде своего рода таблиц (их называют массивами). Язык содержит определенное количество функций, например, функцию синус можно вычислить, просто записав SIN(x), где х - значение.
Хватит подробностей. Наша беседа ни в коей мере не претендует на роль руководства по программированию. Позволили языки уменьшить трудоемкость программирования? Несомненно, да. Прежде всего человек получил возможность не корпеть над бесконечными последовательностями нулей и единиц, перейдя вместо этого к более привычным ему строчкам букв и цифр. Во-вторых, отпала необходимость держать в голове или вырисовывать на листе бумаги все ячейки памяти. При реальном программировании приходится иметь дело с десятками и сотнями тысяч таких ячеек. Отпала необходимость выполнять рутинную работу, например, по оформлению циклов.
Вместе с языками, естественно, появились средства перевода с этих языков на язык машины, так называемые трансляторы. Одновременно с основной функцией перевода трансляторы выполняют также функцию строжайшего контроля соблюдения грамматических правил. Это совершенно необходимо. Как, к. примеру, машина отличает адрес операнда (идентификатор) от адреса команды (метки)? Способ единственный: если после строчки букв и цифр следует двоеточие (так не во всех языках, а только в языке Алгол), значит, это метка. В противном случае - идентификатор.
Строгий грамматический контроль имеет большое положительное значение, так как с его помощью вылавливаются многие ошибки программиста. Увы! Программист продолжает ошибаться, даже пользуясь самым совершенным алгоритмическим языком. Столь щепетильная придирчивость ЭВМ к грамматическим ошибкам заставляет тратить слишком много времени на возвраты программ и исправление ошибок. ЭВМ вполне заслуживает того, чтобы ей доверили самостоятельно исправлять большую часть грамматических ошибок типа забытых запятых.
Нельзя обойти молчанием и то, что появление алгоритмических языков, да еще различных, добавило в изрядно заполненную всевозможными терминами мусорную корзину нашего человеческого языка еще немалую толику. Никогда не забудем, какое количество сил пришлось затратить, чтобы усвоить наконец, что за премудрость кроется под магическим словом "идентификатор"! И какая взяла злость, когда стало ясно, что идентификатор всего лишь адрес ячейки памяти.
Заканчивая рассуждения о языках, мы лишь повторим то, что уже сказано на страницах этой книги по поводу изучения языков вообще. Сейчас много говорят о всеобщей компьютерной грамотности и в первую очередь связывают ее с изучением алгоритмических языков. При этом процесс обучения даже простейшему языку, скажем Бейсику, возводится в рамки самостоятельной сложной проблемы. Мы продолжаем придерживаться собственной точки зрения. Конечно, можно поступать и так: сначала вызубрить наизусть все руководство к языку, а это книжка объемом не менее полусотни страниц, и только потом начинать им пользоваться. При подобной методике процесс обучения займет не меньше чем полгода. Мы настойчиво советуем использовать неоднократно проверенный и на самих себе, и на нескольких сотнях учащихся метод. Выучить только то, что сказано на предыдущих страницах, и ничтоже сумняшеся садиться за клавиатуру ЭВМ. Все остальное придет само, и вы даже не заметите как.
Гувернеры
Помните бессмертные строчки Пушкина?
Судьба Евгения хранила,
Сперва мадам за ним ходила,
Потом месье ее сменил.
И с ЭВМ так же было. Прежде всего ЭВМ научилась говорить. При этом ей предложили сразу несколько языков на выбор, а подчас предлагалось пользоваться несколькими языками одновременно. Каждому языку соответствовала своя программа-транслятор, которая, кроме основной функции собственно перевода с одного языка на другой, выполняла много других. В их числе уже упоминавшееся выявление ошибок, воспринятие текста, вводимого в машину (это делалось разными способами), а также подготовка и вывод текстов, предназначенных для пользования.
Постепенно стало ясно, что совмещать все функции в одной программе-трансляторе нецелесообразно. Почему? Хотя бы по той простой причине, что если машина оперирует сразу с несколькими языками, то и трансляторов в ее памяти хранится несколько, а в определенной части своих функций они дублируют друг друга. Было решено сохранить за трансляторами основную функцию перевода и частично контроля. Кроме того, появилось много разнообразных программ - редакторов, компоновщиков, организаторов, с помощью которых несколько фрагментов, написанных на разных языках, объединялись в единый последовательный текст (одну программу).
Сейчас имеет смысл отметить такую очень важную особенность. Большинство алгоритмических языков являются открытыми в том смысле, что их словарный состав непрерывно пополняется, как, собственно, это и происходит с естественными языками. Что это означает применительно к алгоритмическим языкам? Если вы написали некую программу, например программу для игры в "кошки-мышки", и она оказалась удачной, а главное, есть основания полагать, что она понадобится еще много раз, то эту программу можно разместить в памяти машины на постоянное жительство. Вызов ее из памяти и приведение в действие осуществляются по специальному слову, которое вводится в состав языка, - такое слово получило название макрорасширения.
Гувернеры
По мере работы ЭВМ количество макрорасширений увеличивается, растет объем библиотеки программ. Возникает потребность организовать эту библиотеку точно так же, как это делается с обычными книжными библиотеками. В памяти машины размещают каталог, в котором описания программы располагаются в определенном порядке. Каждое описание содержит назначение программы, язык, на котором она написана, указание по приведению ее в действие и другие данные. При достаточно большом количестве программ подобное каталожное хозяйство оказывается сложным и представляет собой самостоятельную, весьма важную систему ЭВМ.
В одной из предыдущих бесед мы говорили, что большие ЭВМ третьего поколения способны обслуживать одновременно несколько коллективов пользователей. Можно сделать даже более сильное заявление. Один человек-пользователь не в силах загрузить работой ЭВМ третьего поколения, относящуюся к классу больших. Что такое большая ЭВМ? Это мы уточним несколько позже. Так вот, к началу 70-х годов отмеченное обстоятельство представляло собой весьма крупную проблему. В чем же дело? Час работы большой ЭВМ стоит дорого (у нас - порядка 50-60 рублей), причем эти деньги тратятся независимо от того, работает кто-то с ЭВМ или нет. Отсюда и возникла идея организации режима разделения времени, то есть организации одновременной работы ЭВМ с несколькими пользователями.
Владельцев больших ЭВМ беспокоило то обстоятельство, что в ночные часы не удается загрузить ЭВМ работой, так как пользователи предпочитают ночью спать. Между тем выход из положения нашелся. В чем он состоял? Ночью предоставлять машинное время пользователям, проживающим в других часовых поясах. К примеру, вычислительный центр, расположенный в Калифорнии, обслуживал японских пользователей, причем оказалось экономически оправданным даже применение для этих целей спутниковых каналов связи.
Здесь напрашивается весьма существенное уточнение. Говоря о языках, мы отметили, что любой язык заменяет конкретные номера ячеек памяти, хранящих операнды, специальными словами-идентификаторами. Таким образом, возникло разделение устройств ЭВМ на физические и логические. Физическая ячейка памяти - это совершенно конкретная ячейка, имеющая, например, порядковый номер 77500 и расположенная в интегральной схеме на панели запоминающего устройства ЭВМ десятой справа во втором ряду. Эта ячейка обозначается последовательностью символов, например ХУ2, которая и представляет собой идентификатор, или логическую ячейку памяти. По мере развития ЭВМ та же идея начала применяться и к другим устройствам. Автомат, оперирующий с кредитными карточками, представляет собой конкретное физическое устройство. Но в ЭВМ ему присвоен определенный код, и этот код представляет собой логический автомат для чтения кредитных карточек.
Соответствия между логическими и физическими устройствами сохраняются достаточно долго, но могут изменяться. Если некий магазин отказывается от услуг банка, физический автомат в его салоне демонтируется, а принадлежавший автомату код присваивается другому автомату. Более простая, но в то же время чаще встречающаяся ситуация - это когда ЭВМ при необходимости вывести полученный результат отыскивает то устройство вывода, которое в данный момент свободно, и присваивает ему кодовое обозначение.
Итого мы насчитали четыре вида программ: во-первых, программы-трансляторы, во-вторых, программы - редакторы, компоновщики и контролеры, в-третьих, программы - организаторы библиотек, наконец, в-четвертых, программы, создающие и обслуживающие таблицы соответствия между физическими и логическими устройствами. Имеется пятый вид программ, наводящих порядок в очереди пользователей в случае, когда действует система разделения времени. Шестой вид программ управляет работой остальных пяти, выполняет функции администратора.
Все это вместе взятое получило название системы программного обеспечения, или, как часто говорят, операционной системы.
В 60-х и 70-х годах операционные системы стремительно развивались. Дело дошло до того, что в отдельных случаях до 90 процентов ресурсов ЭВМ затрачивалось исключительно на внутренние нужды, то есть на работу операционной системы, и лишь 10 процентов ресурсов доставалось пользователям.
Однако нас с вами сейчас интересует другое. ЭВМ как таковая оказалась отделенной от пользователя прочным кольцом всевозможных программ операционной системы. Единственной ниточкой, связывающей ЭВМ с пользователем, оставался тот или иной язык. Написав программу на определенном языке и передав ее на исполнение, пользователь не имел ни малейшего представления, какие устройства ЭВМ, каким образом и когда выполняют его программу. С течением времени эта языковая ниточка стала еще тоньше.
Подобная изоляция ЭВМ от пользователя часто приобретала физические формы. Во многих вычислительных центрах пользователь даже близко не подпускался к ЭВМ. Программы принимались у него операторами через маленькие окошечки, подобные кассовым. Таким же путем он получал отпечатанные на бумаге результаты. Но опять же не станем вдаваться в подробности, а констатируем главное. По мере развития операционной системы ЭВМ оказалась отделенной от пользователей прочной и высокой стеной всевозможных трансляторов, редакторов и т. п.
Мундир! Один мундир!
Буквально в тот день, когда появились ЭВМ, а может быть даже раньше, родилось и безапелляционное мнение: для того чтобы некоторая задача решалась ЭВМ, она должна быть облачена в мундир, иначе говоря, одета в форму, то есть формализована. Если сказать совсем просто, задача должна быть записана в виде системы математических уравнений. Никому в голову не пришло задуматься, так ли все обстоит на самом деле. Просто раз навсегда было принято, что ЭВМ - машина вычислительная, математическая, выполнять она должна арифметические операции и соответственно этому задача должна быть формализована. Самое поразительное, что подобное мнение до сих пор ни у кого не вызывает сомнений, несмотря на то, что ЭВМ давно научились переводить с одного языка на другой (имеются в виду естественные языки), писать стихи, ставить медицинские диагнозы, создавать совсем неплохие, особенно по современным стандартам, музыкальные произведения и многому другому.
Ровно столько времени, сколько существуют ЭВМ, существуют люди, стремящиеся доказать, что возможности ЭВМ принципиально ограниченны и в области переработки информации ЭВМ никогда не сравняются с людьми. В свое время, примерно в середине 60-х годов, творческие возможности ЭВМ служили предметом для жарких дискуссий. На эту тему писались книги, созывались международные конференции. Кто-то из специалистов тогда пошутил, что понятию "творческая деятельность" может быть дано единственное определение: творчество - это то, чего не могут ЭВМ. При этом, добавил он, по мере внедрения ЭВМ во все новые и новые сферы деятельности это определение должно непрерывно эволюционировать.
Сейчас споры поутихли, но убеждение осталось. Трудно удержаться и не привести здесь частенько повторяемое в литературе высказывание о том, что ученые, как правило, вообще не способны менять своих убеждений. Если в науке случается так, что торжествует некая новая теория, как это в свое время произошло, например, с квантовой физикой, то только потому, что сторонники старой теории постепенно вымирают.
Недавно нам довелось прочитать в одном журнале суждение, с которым хочется поспорить. Его автор вынужден был признать, что в настоящее время ЭВМ играет в шахматы на уровне гроссмейстеров и, несомненно, в ближайшее время не только достигнет, но и превысит высший уровень. Однако тут же добавляет: такая ЭВМ только и может играть в шахматы, а человек-шахматист способен и на многое другое. Вряд ли стоит спорить с тем, что достаточно сменить магнитную ленту и та же ЭВМ, недавно обыгравшая гроссмейстера, превратится в прекрасного врача-диагноста. Тут, как говорится, комментарии излишни.
На затронутую тему мы еще поговорим. Только вот какое соображение приходит в голову. Как сегодня практикуется? Поработав на ЭВМ, человек сразу выключает ее. А почему бы, собственно говоря, не дать ей возможность поразмышлять на досуге? Почему не подключить ЭВМ, скажем, к радиосети, откуда она могла бы черпать новую информацию? Технически это не представляет особых трудностей. ЭВМ давно уже подключены к телефонным сетям и не только воспринимают информацию, но и управляют их работой. Почему бы, наконец, не снабдить ЭВМ органами технического зрения, которыми снабжают роботов, и не дать ей возможность в свободное время понаблюдать окружающий мир?
Так или иначе, но пока мы можем констатировать следующее. С одной стороны, рядовой пользователь, некий специалист, достаточно далекий от математики (биолог, химик, педагог, продавец в магазине), работает с ЭВМ все чаще и чаще. Более того, имеются профессии, например оператор атомной электростанции, где работа вообще немыслима без ЭВМ. С другой стороны, пользователь отделен от ЭВМ не одной, а двумя стенами. Внутреннее кольцо укреплений составляют программисты и созданные ими операционные системы. Внешнее кольцо - алгоритмисты (их называют аналитиками или специалистами по прикладной математике), занимающиеся формализацией - переводом содержания задач с языка пользователя на язык математики.
Хорошо это или плохо? Дать однозначный ответ было бы слишком смело. Но факт остается фактом - пользователь отлучен от ЭВМ, не представляет всех ее возможностей и вряд ли в таких условиях способен реализовать их в достаточной мере. ЭВМ, в свою очередь, отлучена от пользователя, не знает его потребностей, и это в значительной степени лишает ее возможности самосовершенствоваться. При всем при том в мире существует огромная армия (одних программистов насчитывается около миллиона) людей, единственная задача которых - переводить с одного языка на другой. В таких условиях нельзя не задуматься о том, что, вероятно, существуют способы обойтись без посредников. Размышления подобного рода и привели к появлению информатики.