The Hundred-Year Language
Эссе Пола Грэма (апрель 2003, на основе кейноута на PyCon 2003) рассуждает о том, каким будет язык программирования через сто лет. Автор сравнивает эволюцию языков с эволюцией видов: Cobol и, по его прогнозу, Java окажутся тупиковыми ветвями, а главные ветви проходят через языки с маленьким и чистым ядром из небольшого числа аксиом. Грэм утверждает, что по мере роста скорости железа главным ресурсом станет время программиста, а не машинное, и языки смогут избавляться от структур, существующих ради эффективности (отдельные строки, массивы, хеш-таблицы, даже числа), оставляя их в виде указаний компилятору. Он также предсказывает, что параллелизм останется явно запрашиваемой опцией, а не пронизывающей программы по умолчанию, и что дизайн языков всё больше переходит от исследователей к хакерам и прикладным программистам (Perl, Python, Ruby). Главный вывод: столетний язык в принципе можно проектировать уже сейчас, ориентируясь на краткость и минимальное ядро, как водитель целится в дальнюю точку, а не на капот.
Апрель 2003
(Это эссе основано на кейноут-докладе на PyCon 2003.)
Трудно предсказать, какой будет жизнь через сто лет. С уверенностью можно сказать лишь несколько вещей. Мы знаем, что все будут ездить на летающих машинах, что нормы зонирования смягчат, разрешив здания в сотни этажей, что бóльшую часть времени будет темно и что все женщины будут обучены боевым искусствам. Здесь я хочу приблизить одну деталь этой картины. На каком языке программирования будут писать софт, управляющий этими летающими машинами?
Об этом стоит думать не столько потому, что мы реально доживём до использования этих языков, сколько потому, что, если повезёт, мы будем пользоваться языками на пути от нынешней точки к той.
Я думаю, что языки, подобно видам, образуют эволюционные деревья, и от ствола повсюду отходят тупиковые ветви. Это уже происходит у нас на глазах. Cobol при всей его былой популярности, похоже, не оставил интеллектуальных потомков. Это эволюционный тупик — язык-неандерталец.
Я предсказываю такую же судьбу Java. Мне иногда пишут: «Как вы можете говорить, что Java не окажется успешным языком? Он уже успешный язык». И я согласен, что это так, если мерить успех площадью полок, занятых книгами о нём (особенно отдельными книгами), или числом студентов, считающих, что должны его выучить ради работы. Когда я говорю, что Java не окажется успешным языком, я имею в виду нечто более конкретное: что Java окажется эволюционным тупиком, как Cobol.
Это просто догадка. Я могу ошибаться. Моя цель здесь не в том, чтобы поругать Java, а в том, чтобы поднять вопрос об эволюционных деревьях и заставить людей спрашивать: где на дереве язык X? Спрашивать это надо не для того, чтобы наши призраки через сто лет могли сказать «я же говорил». А потому, что держаться поближе к основным ветвям — полезная эвристика для поиска языков, на которых хорошо программировать прямо сейчас.
В любой момент времени вам, скорее всего, лучше всего на основных ветвях эволюционного дерева. Даже когда неандертальцев ещё было полно, быть одним из них было, должно быть, паршиво. Кроманьонцы постоянно приходили бы, били вас и отбирали еду.
Я хочу знать, какими будут языки через сто лет, чтобы понимать, на какую ветвь дерева ставить сейчас.
Эволюция языков отличается от эволюции видов тем, что ветви могут сходиться. Ветвь Fortran, например, похоже, сливается с потомками Algol. Теоретически это возможно и для видов, но вряд ли это происходило с чем-то крупнее клетки.
Сходимость более вероятна для языков отчасти потому, что пространство возможностей меньше, а отчасти потому, что мутации не случайны. Дизайнеры языков сознательно перенимают идеи из других языков.
Дизайнерам языков особенно полезно думать о том, куда вероятно ведёт эволюция языков программирования, потому что они могут соответственно корректировать курс. В таком случае «оставаться на основной ветви» становится не просто способом выбрать хороший язык. Это становится эвристикой для принятия правильных решений при проектировании языка.
Любой язык программирования можно разделить на две части: некоторый набор фундаментальных операторов, играющих роль аксиом, и остальная часть языка, которую в принципе можно записать через эти фундаментальные операторы.
Я думаю, фундаментальные операторы — важнейший фактор долгосрочного выживания языка. Остальное можно изменить. Это как правило, что при покупке дома прежде всего нужно учитывать местоположение. Всё остальное можно исправить потом, а местоположение — нет.
Я считаю важным не только удачный выбор аксиом, но и то, чтобы их было мало. Математики всегда так относились к аксиомам — чем меньше, тем лучше — и, по-моему, они на верном пути.
По меньшей мере полезным упражнением должно быть пристально вглядеться в ядро языка и посмотреть, нет ли аксиом, которые можно было бы выполоть. За свою долгую карьеру неряхи я обнаружил, что хлам плодит хлам, и наблюдал это как в софте, так и под кроватями и в углах комнат.
У меня есть подозрение, что основные ветви эволюционного дерева проходят через языки с самым маленьким и чистым ядром. Чем больше частей языка можно написать на нём самом, тем лучше.
Конечно, я делаю большое допущение, даже задаваясь вопросом, какими будут языки программирования через сто лет. А будем ли мы вообще писать программы через сто лет? Не будем ли мы просто говорить компьютерам, что мы хотим, чтобы они делали?
Пока что в этой области не было большого прогресса. Я предполагаю, что через сто лет люди по-прежнему будут говорить компьютерам, что делать, с помощью программ, которые мы узнали бы как таковые. Возможно, будут задачи, которые мы сегодня решаем, написав программу, и которые через сто лет не потребуют для решения никаких программ, но я думаю, что программирования того типа, которым мы занимаемся сегодня, останется немало.
Может показаться самонадеянным думать, что кто-то способен предсказать, как будет выглядеть какая-либо технология через сто лет. Но вспомните, что за нами уже стоит почти пятьдесят лет истории. Заглядывать на сто лет вперёд — вполне постижимая идея, если учесть, как медленно языки эволюционировали за последние пятьдесят.
Языки эволюционируют медленно, потому что они не совсем технологии. Языки — это нотация. Программа — это формальное описание задачи, которую вы хотите, чтобы компьютер вам решил. Так что темп эволюции языков программирования ближе к темпу эволюции математической нотации, чем, скажем, транспорта или связи. Математическая нотация тоже эволюционирует, но не теми гигантскими скачками, что мы видим в технологиях.
Из чего бы ни были сделаны компьютеры через сто лет, безопасно предсказать, что они будут гораздо быстрее, чем сейчас. Если закон Мура продолжит выдавать своё, они будут в 74 квинтиллиона (73 786 976 294 838 206 464) раз быстрее. Это сложно представить. И, по правде говоря, самым вероятным предсказанием по части скорости может быть то, что закон Мура перестанет работать. Что-либо, что должно удваиваться каждые восемнадцать месяцев, вероятно, рано или поздно упрётся в какой-то фундаментальный предел. Но мне нетрудно поверить, что компьютеры будут намного быстрее. Даже если они окажутся всего в жалкий миллион раз быстрее, это должно существенно изменить правила игры для языков программирования. Среди прочего, появится больше места для того, что сейчас считалось бы медленными языками, то есть языками, не дающими очень эффективного кода.
И всё же некоторые приложения по-прежнему будут требовать скорости. Часть задач, которые мы хотим решать на компьютерах, порождена самими компьютерами; например, скорость, с которой нужно обрабатывать видеокадры, зависит от того, как быстро их может генерировать другой компьютер. И есть ещё класс задач с принципиально неограниченной способностью поглощать такты: рендеринг изображений, криптография, симуляции.
Если одни приложения смогут становиться всё более неэффективными, пока другие будут требовать всей скорости, какую только может выдать железо, то более быстрые компьютеры будут означать, что языкам придётся покрывать всё более широкий диапазон уровней эффективности. Это уже у нас на глазах. Текущие реализации некоторых популярных новых языков шокирующе расточительны по меркам предыдущих десятилетий.
Это происходит не только с языками программирования. Это общая историческая тенденция. По мере улучшения технологий каждое поколение может позволить себе то, что предыдущее сочло бы расточительством. Люди тридцать лет назад поразились бы, насколько небрежно мы делаем междугородние звонки. Люди сто лет назад поразились бы ещё сильнее, узнав, что однажды посылка из Бостона в Нью-Йорк будет ехать через Мемфис.
Я уже сейчас могу сказать вам, что произойдёт со всеми лишними тактами, которые более быстрое железо даст нам в ближайшие сто лет. Почти все они будут потрачены впустую.
Я учился программировать, когда вычислительная мощность была в дефиците. Я помню, как убирал все пробелы из своих программ на Basic, чтобы они влезли в память 4К TRS-80. Мысль обо всём этом потрясающе неэффективном софте, который сжигает такты, делая одно и то же снова и снова, кажется мне какой-то противной. Но я думаю, что моя интуиция здесь ошибается. Я как человек, выросший в бедности и не способный заставить себя потратить деньги даже на что-то важное, например, поход к врачу.
Какие-то виды расточительства действительно отвратительны. Внедорожники, к примеру, по сути были бы мерзкими, даже если бы ездили на топливе, которое никогда не кончается и не даёт загрязнения. Внедорожники мерзки потому, что они — решение мерзкой задачи. (Как сделать минивэны более мужественными на вид.) Но не всякое расточительство плохо. Теперь, когда у нас есть инфраструктура, чтобы его себе позволить, считать минуты междугородних разговоров начинает казаться мелочностью. Если есть ресурсы, элегантнее воспринимать все телефонные звонки как одну сущность, где бы ни находился собеседник.
Бывает хорошее расточительство, бывает плохое. Меня интересует хорошее — такое, при котором, тратя больше, мы получаем более простые решения. Как мы воспользуемся возможностями впустую тратить такты, которые даст нам новое, более быстрое железо?
Стремление к скорости настолько глубоко в нас укоренено вместе с нашими хилыми компьютерами, что преодолеть его потребует сознательного усилия. В дизайне языков мы должны сознательно искать ситуации, где можно обменять эффективность даже на малейшее увеличение удобства.
Большинство структур данных существуют ради скорости. Например, во многих современных языках есть и строки, и списки. С точки зрения семантики строки — это более или менее подмножество списков, в которых элементы являются символами. Так зачем нужен отдельный тип данных? На самом деле не нужен. Строки существуют только ради эффективности. Но захламлять семантику языка хаками, заставляющими программы работать быстрее, — это убожество. Наличие строк в языке выглядит как случай преждевременной оптимизации.
Если мы воспринимаем ядро языка как набор аксиом, то добавлять лишние аксиомы, не добавляющие выразительной силы, исключительно ради эффективности — наверняка убогая идея. Эффективность важна, но я не думаю, что это правильный путь её получить.
Правильный способ решить эту проблему, думаю, — отделить смысл программы от деталей реализации. Вместо того чтобы иметь и списки, и строки, иметь только списки, с каким-то способом давать компилятору подсказки для оптимизации, которые позволят ему при необходимости расположить строки как непрерывные байты.
Поскольку в большей части программы скорость не важна, обычно вам не придётся возиться с таким микроменеджментом. Это будет всё более верно по мере роста скорости компьютеров.
Говорить меньше о реализации также должно делать программы более гибкими. Спецификации меняются по ходу написания программы, и это не только неизбежно, но и желательно.
Слово «essay» происходит от французского глагола «essayer», что значит «пробовать». Эссе в исходном смысле — это то, что вы пишете, пытаясь в чём-то разобраться. Это бывает и в софте. Я думаю, некоторые из лучших программ были эссе в том смысле, что авторы, начиная их, точно не знали, что именно они пытаются написать.
Хакеры Lisp уже знают о ценности гибкости в выборе структур данных. Мы склонны писать первую версию программы так, чтобы всё делалось на списках. Эти начальные версии могут быть настолько шокирующе неэффективными, что требуется сознательное усилие не думать о том, что они делают, — так же, как, по крайней мере для меня, поедание стейка требует сознательного усилия не думать о том, откуда он взялся.
Чего программисты через сто лет будут искать больше всего — это язык, на котором можно с минимально возможными усилиями набросать неправдоподобно неэффективную версию 1 программы. По крайней мере, так бы мы это описали в сегодняшних терминах. Сами они скажут, что хотят язык, на котором легко программировать.
Неэффективный софт — это не убожество. Убожество — это язык, заставляющий программистов делать ненужную работу. Тратить впустую время программиста — вот настоящая неэффективность, а не машинное время. Это будет становиться всё яснее по мере того, как компьютеры будут становиться быстрее.
Я думаю, отказ от строк — это уже то, о чём мы могли бы себе позволить задуматься. Мы сделали это в Arc, и, похоже, это выигрыш; некоторые операции, которые было бы неудобно описывать как регулярные выражения, легко описываются как рекурсивные функции.
Как далеко зайдёт это уплощение структур данных? Я могу представить варианты, которые шокируют даже меня с моим сознательно расширенным сознанием. Откажемся ли мы, к примеру, от массивов? В конце концов, это всего лишь подмножество хеш-таблиц, в которых ключи — это векторы целых чисел. Заменим ли мы сами хеш-таблицы списками?
Есть перспективы и пошокирующее. В Lisp, который McCarthy описал в 1960 году, например, не было чисел. Логически отдельное понятие чисел иметь не нужно, потому что их можно представлять как списки: целое число n можно представить как список из n элементов. Так можно заниматься математикой. Просто это невыносимо неэффективно.
На практике никто и не предлагал реализовывать числа как списки. На самом деле статья McCarthy 1960 года в то время вообще не предназначалась для реализации. Это было теоретическое упражнение, попытка создать более элегантную альтернативу машине Тьюринга. Когда же кто-то неожиданно взял эту статью и перевёл её в работающий интерпретатор Lisp, числа, конечно, представлялись не списками; они представлялись в двоичном виде, как и в любом другом языке.
Может ли язык программирования зайти настолько далеко, чтобы избавиться от чисел как фундаментального типа данных? Я задаю этот вопрос не столько всерьёз, сколько как способ сыграть в «слабо» с будущим. Это как гипотетический случай встречи неудержимой силы с неподвижным объектом — здесь это встреча невообразимо неэффективной реализации с невообразимо большими ресурсами. Не вижу, почему нет. Будущее довольно длинное. Если есть что-то, что мы можем сделать, чтобы уменьшить число аксиом в ядре языка, то на эту сторону, похоже, и стоит ставить при t, стремящемся к бесконечности. Если идея всё ещё кажется невыносимой через сто лет, возможно, она перестанет казаться такой через тысячу.
Чтобы было понятно: я не предлагаю, чтобы все численные вычисления действительно выполнялись с помощью списков. Я предлагаю, чтобы ядро языка, до каких-либо дополнительных нотаций о реализации, было определено именно так. На практике любая программа, которой надо хоть сколько-то заниматься математикой, скорее всего, представляла бы числа в двоичном виде, но это была бы оптимизация, а не часть семантики ядра языка.
Ещё один способ сжигать такты — иметь множество слоёв ПО между приложением и железом. Это тоже тенденция, которую мы уже наблюдаем: многие современные языки компилируются в байт-код. Bill Woods однажды сказал мне, что, как правило большого пальца, каждый слой интерпретации обходится в коэффициент 10 по скорости. Эта дополнительная плата покупает вам гибкость.
Самая первая версия Arc была крайним случаем такой многослойной медлительности — с соответствующими преимуществами. Это был классический «метациркулярный» интерпретатор, написанный поверх Common Lisp, с явным семейным сходством с функцией eval, определённой в оригинальной статье McCarthy о Lisp. Вся штука была всего парой сотен строк кода, поэтому её было очень легко понимать и менять. Common Lisp, который мы использовали, CLisp, сам работает поверх интерпретатора байт-кода. То есть у нас было два уровня интерпретации, один из них (верхний) шокирующе неэффективный, и язык был пригоден к использованию. Едва пригоден, признаю, но пригоден.
Писать ПО в виде нескольких слоёв — мощный приём даже внутри приложений. Программирование снизу вверх означает писать программу как серию слоёв, каждый из которых служит языком для слоя выше. Этот подход обычно даёт меньшие и более гибкие программы. Это также лучший путь к тому Святому Граалю — переиспользуемости. Язык по определению переиспользуем. Чем большую часть вашего приложения вы можете протолкнуть вниз в язык для написания приложений такого типа, тем большая часть вашего софта будет переиспользуема.
Каким-то образом идея переиспользуемости в 1980-х оказалась прицеплена к объектно-ориентированному программированию, и никакого количества доказательств обратного, похоже, недостаточно, чтобы оторвать её. Но хотя часть объектно-ориентированного ПО действительно переиспользуема, переиспользуемой её делает её устроенность снизу вверх, а не объектная ориентированность. Возьмите библиотеки: они переиспользуемы потому, что они — язык, написаны они в объектно-ориентированном стиле или нет.
Кстати, я не предсказываю гибель объектно-ориентированного программирования. Хотя я не думаю, что оно много даёт хорошим программистам, кроме как в некоторых специализированных областях, оно неотразимо для больших организаций. Объектно-ориентированное программирование предлагает устойчивый способ писать спагетти-код. Оно позволяет наращивать программы как серию заплаток.
Большие организации всегда склонны разрабатывать ПО именно так, и я ожидаю, что через сто лет это будет так же верно, как и сегодня.
Раз уж мы говорим о будущем, нам лучше поговорить о параллельных вычислениях, потому что именно там, похоже, обитает эта идея. То есть, в какой бы момент вы ни говорили, параллельные вычисления, кажется, — это то, что произойдёт в будущем.
Догонит ли когда-нибудь будущее эту идею? Люди говорят о параллельных вычислениях как о чём-то неизбежно близком как минимум 20 лет, и пока что они не сильно повлияли на практику программирования. Или повлияли? Дизайнерам чипов уже приходится об этом думать, как и тем, кто пишет системное ПО для многопроцессорных компьютеров.
Реальный вопрос в том, насколько высоко по лестнице абстракции поднимется параллелизм. Затронет ли он через сто лет даже прикладных программистов? Или это будет то, о чём думают разработчики компиляторов, но что обычно невидимо в исходном коде приложений?
Одно, что кажется вероятным, — большая часть возможностей для параллелизма будет растрачена впустую. Это частный случай моего более общего предсказания, что бóльшая часть лишней вычислительной мощности, которую нам дадут, уйдёт впустую. Я думаю, что, как и с потрясающей скоростью лежащего в основе железа, параллелизм будет чем-то, что доступно, если явно его попросить, но обычно не используется. Это значит, что параллелизм, который будет у нас через сто лет, за исключением специальных приложений, не будет массовым параллелизмом. Я думаю, для обычных программистов это будет скорее возможность форкнуть несколько процессов, которые в итоге выполняются параллельно.
И это, как и запрос конкретных реализаций структур данных, будет тем, что вы делаете довольно поздно в жизни программы, пытаясь её оптимизировать. Версии 1 обычно будут игнорировать любые выгоды, которые можно получить от параллельных вычислений, точно так же, как они будут игнорировать выгоды от конкретных представлений данных.
За исключением специальных типов приложений, через сто лет параллелизм не будет пронизывать пишущиеся программы. Если бы это было так, это было бы преждевременной оптимизацией.
Сколько языков программирования будет через сто лет? В последнее время вроде бы появилось огромное количество новых языков программирования. Отчасти причина в том, что более быстрое железо позволило программистам делать разные компромиссы между скоростью и удобством, в зависимости от приложения. Если это реальный тренд, то железо, которое будет у нас через сто лет, должно лишь усилить его.
И всё же через сто лет, возможно, будет лишь несколько широко используемых языков. Отчасти я это говорю из оптимизма: похоже, что при действительно хорошей работе можно сделать язык, идеально подходящий для написания медленной версии 1 и при этом при правильных подсказках компилятору для оптимизации выдающий и очень быстрый код, когда это нужно. Так что, поскольку я оптимист, предскажу, что, несмотря на огромный разрыв между приемлемой и максимальной эффективностью, у программистов через сто лет будут языки, способные покрыть большую его часть.
По мере того как этот разрыв расширяется, профилировщики будут становиться всё более важными. Сейчас профилированию уделяют мало внимания. Многие, похоже, до сих пор считают, что способ получить быстрые приложения — писать компиляторы, генерирующие быстрый код. По мере расширения разрыва между приемлемой и максимальной производительностью будет становиться всё яснее, что способ получить быстрые приложения — иметь хорошего проводника от одной к другой.
Когда я говорю, что языков, возможно, будет немного, я не включаю сюда предметно-ориентированные «маленькие языки». Я думаю, такие встроенные языки — отличная идея, и ожидаю их распространения. Но я ожидаю, что они будут написаны достаточно тонкой обёрткой, чтобы пользователи видели через неё язык общего назначения.
Кто будет проектировать языки будущего? Один из самых увлекательных трендов последних десяти лет — рост языков с открытым исходным кодом, таких как Perl, Python и Ruby. Дизайн языков переходит к хакерам. Результаты пока что беспорядочные, но обнадёживающие. В Perl, например, есть несколько ошеломительно новых идей. Многие из них ошеломительно плохи, но так всегда бывает с амбициозными попытками. При нынешнем темпе мутаций бог знает, во что Perl сможет эволюционировать за сто лет.
Неправда, что «кто не умеет делать — учит» (некоторые из лучших известных мне хакеров — профессора), но правда то, что есть много вещей, которые те, кто учит, делать не могут. Исследовательская работа накладывает сковывающие кастовые ограничения. В любой академической области есть темы, которыми можно заниматься, и темы, которыми нельзя. К сожалению, различие между допустимыми и запрещёнными темами обычно основано на том, насколько интеллектуально звучит работа в описании в исследовательских статьях, а не на том, насколько она важна для получения хороших результатов. Крайний случай — это, пожалуй, литература; люди, изучающие литературу, редко говорят что-то, что было бы хоть сколько-нибудь полезно тем, кто её создаёт.
Хотя в естественных науках ситуация лучше, перекрытие между тем, чем разрешается заниматься, и тем, что даёт хорошие языки, удручающе мало. (Olin Shivers красноречиво поворчал об этом.) Например, типы, похоже, неиссякаемый источник исследовательских статей, несмотря на то что статическая типизация, кажется, исключает настоящие макросы — без которых, по моему мнению, ни один язык не стоит использования.
Тенденция не только в том, что языки развиваются как open-source проекты, а не как «исследования», но и в том, что языки проектируются прикладными программистами, которым нужно ими пользоваться, а не разработчиками компиляторов. Это, похоже, хороший тренд, и я ожидаю его продолжения.
В отличие от физики через сто лет, которую почти наверняка невозможно предсказать, я думаю, что в принципе можно уже сейчас спроектировать язык, который понравится пользователям через сто лет.
Один из способов проектировать язык — просто записать программу, которую вы хотели бы иметь возможность написать, независимо от того, есть ли компилятор, который сможет её перевести, или железо, которое сможет её запустить. Так можно предполагать неограниченные ресурсы. Кажется, мы должны быть способны представлять себе неограниченные ресурсы сегодня не хуже, чем через сто лет.
Какую программу хотелось бы написать? Какую угодно, лишь бы поменьше работы. Не совсем так: какую угодно, с какой было бы меньше всего работы, если бы ваши представления о программировании не были уже сформированы языками, к которым вы сейчас привыкли. Такое влияние может быть настолько всепроникающим, что преодолеть его требует огромных усилий. Казалось бы, столь ленивым существам, как мы, должно быть очевидно, как выразить программу с минимальными усилиями. На деле же наши представления о возможном настолько ограничены языком, на котором мы думаем, что более простые формулировки программ кажутся очень удивительными. Это то, что приходится открывать, а не то, во что естественно сваливаешься.
Один полезный приём здесь — использовать длину программы как приближение к тому, сколько труда нужно для её написания. Не длину в символах, конечно, а длину в различимых синтаксических элементах — по сути, размер дерева разбора. Может быть, не совсем верно, что самая короткая программа — это та, на которую нужно меньше всего труда, но это достаточно близко, чтобы вам лучше было целиться в твёрдую мишень краткости, чем в близкую, но размытую мишень минимума труда. Тогда алгоритм для проектирования языка становится таким: посмотри на программу и спроси, есть ли способ записать её короче?
На практике написание программ на воображаемом столетнем языке будет работать в разной степени в зависимости от того, насколько вы близки к ядру. Процедуры сортировки можно написать уже сейчас. Но какие библиотеки могут понадобиться через сто лет, сейчас было бы трудно предсказать. Многие библиотеки, надо полагать, будут для предметных областей, которых ещё даже не существует. Если SETI@home сработает, например, нам понадобятся библиотеки для общения с инопланетянами. Если, конечно, они не настолько продвинутые, что уже общаются в XML.
С другой стороны, я думаю, что ядро языка может быть спроектировано уже сегодня. Более того, кое-кто мог бы возразить, что оно в основном уже было спроектировано в 1958 году.
Если бы столетний язык был доступен сегодня, захотели бы мы на нём программировать? Один из способов ответить на этот вопрос — оглянуться назад. Если бы современные языки программирования были доступны в 1960 году, захотел ли бы кто-нибудь ими пользоваться?
В каком-то смысле ответ — нет. Современные языки предполагают инфраструктуру, которой не было в 1960-м. Например, язык, в котором значимы отступы, как Python, не очень хорошо работал бы на принтерных терминалах. Но, отложив такие проблемы в сторону — предположив, например, что программы писались бы все просто на бумаге — понравилось ли бы программистам 1960-х годов писать программы на тех языках, которые мы используем сейчас?
Я думаю, да. У некоторых, менее воображаемых, с артефактами ранних языков, встроенными в их представления о том, что такое программа, могли быть проблемы. (Как можно манипулировать данными, не занимаясь арифметикой указателей? Как реализовывать блок-схемы без goto?) Но я думаю, что самые умные программисты не имели бы никаких проблем с тем, чтобы извлечь максимум из современных языков, если бы они у них были.
Если бы столетний язык был у нас сейчас, он, как минимум, был бы прекрасным псевдокодом. А что насчёт использования его для написания софта? Поскольку столетнему языку нужно будет генерировать быстрый код для некоторых приложений, по всей видимости, он мог бы генерировать код, достаточно эффективный, чтобы приемлемо работать на нашем железе. Возможно, нам пришлось бы давать больше подсказок для оптимизации, чем пользователям через сто лет, но это всё равно могло бы быть чистым выигрышем.
Теперь у нас есть две идеи, которые, если их соединить, предполагают интересные возможности: (1) столетний язык в принципе мог бы быть спроектирован сегодня, и (2) такой язык, если бы он существовал, мог бы быть хорош для программирования сегодня. Когда видишь эти идеи рядом, трудно не подумать: а почему бы не попробовать написать столетний язык прямо сейчас?
Когда работаешь над дизайном языка, думаю, полезно иметь такую цель и сознательно держать её в уме. Когда учишься водить, один из принципов, которым вас учат — выравнивать машину не по линии капота относительно нарисованных на дороге полос, а целясь в какую-то точку вдали. Даже если вас волнует только то, что случится в ближайшие десять футов, это правильный ответ. Думаю, мы можем и должны делать то же самое с языками программирования.
Примечания
Я полагаю, Lisp Machine Lisp был первым языком, воплотившим принцип, что объявления (за исключением объявлений динамических переменных) — это всего лишь подсказки для оптимизации и не меняют смысла корректной программы. Common Lisp, кажется, был первым, кто заявил это явно.
Спасибо Trevor Blackwell, Robert Morris и Dan Giffin за чтение черновиков, а также Guido van Rossum, Jeremy Hylton и остальной команде Python за приглашение выступить на PyCon.