Как лень подтолкнула Джона Бэкуса к разработке языков программирования

«Большая часть моей работы связана с ленью. Мне не нравилось писать программы, и поэтому… я начал работать над системой программирования, чтобы упростить написание программ».

- Джон Бэкус (1924–2007)

Ученые-компьютерщики определенно ленивы. Я намеренно говорю положительно ленивый. Когда ученый-компьютерщик сталкивается с задачей, он делает все возможное, чтобы сконцентрироваться на тех частях проблемы, которые имеют значение. Все кропотливое, что он может делегировать автомату, чтобы избежать ненужной работы, тем лучше. Поэтому, когда Джон Бэкус, всю жизнь работавший в IBM, сказал, что его мотивацией была лень, он на самом деле сказал нечто очень важное.

Когда мы думаем о тех, кто совершил великие открытия, мы обычно думаем о людях, которые изо всех сил старались или потратили часы тяжелого труда сверх того, что большинство из нас могло бы вынести. Возможно, это Колумб, проводящий месяцы в море, пересекая Атлантику; может быть, Дарвин десятилетиями путешествует по миру и кропотливо собирает доказательства эволюции; или Эйнштейн, совершающий революцию в физике и доводящий себя до изнеможения в процессе. «Ленивый» — это слово далеко от наших мыслей, когда мы размышляем об этих людях. Информатика — это тяжелая работа, поверьте мне. Но особенность этой области заключается в том, что многие достижения происходят из-за того типа лени, о котором говорил Бэкус. Мы видели пример этого в более ранней статье, когда Леонард Эйлер искал конкретный маршрут через мосты Кёнгисберга. Вместо того чтобы проверить все возможные маршруты, Эйлер поленился. Он атаковал суть проблемы и нашел кратчайший путь, а в процессе придумал теорию графов.

Впрочем, вернемся к Бакусу. Программировать на ассемблере было очень сложно. Бэкус ненавидел это и пытался найти способ избежать этого. При этом он и его команда в IBM совершили один из самых важных прорывов в истории программирования, который принес ему в 1977 году премию Тьюринга ACM[1]. В примечании к награде говорится, что Бэкус получил ее за глубокий, влиятельный и продолжительный вклад в разработку практических систем программирования высокого уровня…. Так что же это были за системы программирования, которые он разработал, чтобы облегчить себе жизнь?

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

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

Что было необходимо, думал Бэкус, так это система, которая была бы тесно связана с тем, как люди естественным образом думают об алгоритмах. Язык ассемблера заставлял мыслить низкоуровневыми терминами, глубоко укоренившимися в недрах компьютера. Новая система Бэкуса выражала решения в терминах более высокого уровня, которые были более чисто математическими. Он создал FORTRAN (от FORmula TRANslation), первый полнофункциональный язык программирования высокого уровня. FORTRAN позволял кому-то писать программы, которые концептуально были намного ближе к алгоритму в их голове. Многие утомительные детали, такие как ячейки памяти, аккумуляторы и низкоуровневые машинные инструкции, не были видны — они были скрыты языком программирования. Несмотря на то, что он не устранил все технические детали, FORTRAN добился большого успеха. Вскоре последовали другие языки программирования, каждый со своим нелепым названием, например, ALGOL, COBOL, LISP или BASIC (строчные буквы еще не были изобретены).

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

Вот такая программа встала у Бэкуса в нос. Это очень простая программа (поверьте мне!), написанная на языке ассемблера и используемая для поиска наибольшего числа в несортированном списке чисел.

; program starts here
1: LDA $14
2: STA $13
3: LDA ($14)
4: INC
5: STA $14
6: LDA ($14)
7: BNG $12
8: CMP $13
9: BLT $3
10: STA $13
11: JMP $3
12: PRINT $13
; data starts here
13: 0  ; the current largest number
14: 15 ; the ADDRESS of the current examined number
15: 3  ; this is the start of the list
16: 7
17: 4
18: -1 ; this marks the end of the list

Если вы никогда в жизни не занимались программированием, вы, вероятно, думаете про себя: «Конечно, я этого не понимаю, но я не должен понимать. Вероятно, это имеет смысл для программиста». Это верно, но это упускает суть. Программисты могут понять этот код, но это требует некоторых усилий даже от талантливого программиста. Есть много технических деталей, о которых программист должен беспокоиться в дополнение к проблеме.

Давайте сравним ее с той программой, которую предпочитал писать Бэкус.

1 LET HIGHEST = 0
2 FOR EACH N IN NUMBERS
3   IF N > HIGHEST THEN LET HIGHEST = N
4 NEXT

Эта программа делает то же самое, что и предыдущая, за исключением того, что она написана на языке программирования BASIC, который появился в 1964 году. У начинающего программиста с базовыми знаниями алгебры не должно возникнуть проблем с ее освоением. Даже если вы никогда раньше не занимались программированием, вы, вероятно, обретете какой-то смысл во время чтения.

Если это не совсем понятно для вас, вот важные моменты:

  • Входные данные для программы — это список чисел, названных (воображаемо) ЧИСЛАМИ.
  • Строка 1 инициализирует переменную с именем HIGHEST, которая содержит значение наибольшего найденного числа.
  • Строка 2 открывает цикл for, который представляет собой форму итерации. Его задача — запустить все инструкции между собой и следующей инструкцией NEXT (в данном случае есть только одна инструкция: строка 3). Он повторяет операторы для каждого элемента в NUMBERS. Таким образом, если в NUMBERS есть три элемента, строка 3 будет выполнена три раза.
  • Каждый раз, когда начинается новое выполнение цикла, N присваивается значение текущего исследуемого элемента. Если бы NUMBERS содержало 3, 7 и 4, то выполняется первая временная строка 3, N содержала бы 3; во второй раз N будет содержать 7; при последнем выполнении N будет содержать 4.
  • Строка 3 сравнивает текущее проверяемое число с наибольшим известным числом. Если он больше, наибольшее число заменяется текущим.
  • Строка 4 говорит компьютеру перейти к следующему элементу в списке. Если достигнут конец списка, компьютер выходит из цикла.

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

Не все языки высокого уровня так дружелюбны, как BASIC, но во многих отношениях они определенно превосходят язык ассемблера. Они позволяют программистам быть более продуктивными, делать меньше ошибок, гораздо меньше отвлекаться на ненужные детали и писать более общие программы.

Это отрывок из моей книги Коричневые псы и парикмахеры: что такое информатика?. Введение в информатику для всех, специальные знания не требуются. Доступно здесь.

1 Премия Тьюринга — своего рода Нобелевская премия по компьютерным наукам, названная в честь покойного Алана Тьюринга.