Я программирую с восьми лет, и основную часть жизни был разработчиком в том или ином качестве. На протяжении своей жизни кодера, как любителя, так и профессионала, я изучил множество языков программирования, которые казались клонами друг друга. Но было и несколько языков, изменивших мой взгляд на программирование, а то и мышление в целом.
Я перечислю их в том порядке, в котором узнавал о них. В большинстве случаев я буду ассоциировать функциональность с языками, в которых они появились не впервые. Это не ошибка, я просто хочу показать, когда узнал об этих возможностях.
Первый Basic с нумерацией строк давно мёртв, но его наследие живёт в VB.Net, VBA, а также в современных динамических языках (Python, JavaScript и так далее).
Наверно, этот язык сильнее всего повлиял на моё формирование как программиста. Подростком я выпустил несколько приложений на Turbo Pascal, в том числе и одно коммерческое (хотя, если откровенно, основную часть работы выполнил Алан Фриш).
Несколько лет спустя, всё ещё подростком, я попробовал перейти на C, и был немного разочарован, обнаружив, что, по сути, это такой же язык, только читать его сложнее (что за странный цикл for с тремя компонентами?), он больше подвержен ошибкам (дальние указатели? серьёзно?) и с зияющей нехваткой некоторых возможностей (как это так — нет модулей?), поэтому я не буду включать C в этот список.
Язык Pascal по-прежнему существует как Turbo Pascal, Lazarus Pascal и Delphi, но ещё и продолжил своё развитие в Ada (из-за его синтаксиса) и во всей существующей документации (JavaDoc, rustdoc, Sphinx, Doxygen и так далее), ведь первый инструмент для разработки документации (WEB) был спроектирован для и на Turbo Pascal.
Одно из основных ограничений Turbo Pascal заключалось в том, что его BGI (API для общения с графическим адаптером) был ограничен 16 цветами и относительно низкими разрешениями. Когда появились более современные графические карты, все разработчики внезапно начали учить язык ассемблера, чтобы иметь возможность общаться с устройствами. Я не стал исключением.
Сегодня очень немногие люди пишут на языке ассемблера вручную, потому что это не особо полезно и не портируемо на 100%, но, разумеется, он всё равно присутствует внутри вашего компилятора или JIT. Я очень часто вижу, как разработчик на Rust или C++ демонстрирует дизассемблированную версию своего двоичного файла, и это напоминает мне о старых (не таких уж) добрых временах.
На другой части спектра находился HyperCard — язык программирования, придуманный для тех, кто не хочет изучать языки программирования. Он выглядел как приложение для рисования, но можно было использовать встроенный язык, чтобы превратить его в полнофункциональную IDE, а также писать новые программы.
Взрыв мозга: мой первый скриптовый язык, хотя в то время я этого и не понимал.
Взрыв мозга: программирование на почти естественном языке.
Взрыв мозга: стек и шаблоны, мои первые абстракции UX.
Взрыв мозга: программирование как форма беседы между программистом и компьютером.
Взрыв мозга: сборка мусора (хотя тогда я этого ещё не осознавал).
Взрыв мозга (в плохую сторону): невозможность портирования кода на платформы, не связанные с Apple; вероятно, это одна из причин того, что сегодня я в основном придерживаюсь опенсорса.
Наверно, этот язык стал первоосновой для всего «визуального», от Visual Basic
и Visual Studio до любого инструмента для рисования UX. Кроме того, в какой-то степени, HyperCard стал одним из предков веба. Время от времени я наблюдаю возрождение какого-нибудь потомка HyperCard, но надолго их обычно не хватает.
Разумеется, многие из этих идей используются и в SmallTalk; вероятно, он более революционен, но я изучил SmallTalk гораздо позже, поэтому взорвать мой мозг по этим пунктам ему уже не удалось!
Caml (позже OCaml) стал для меня неожиданностью. Я был пресыщенным студентом-первокурсником, уверенным, что после выпуска коммерческого ПО знаю уже всё; обычно я лучше владел программированием, чем учителя программирования в старшей школе, и это, разумеется, означало, что я лучший во всём. Я прочитал документацию OCaml ещё до первой лекции и ошибочно понял «полиморфизм» (сегодня мы называем это «дженериками») как «слабую типизацию». Как же я ошибался. На первой лекции преподаватель показал нам, как обходить дерево на OCaml. Это был крайне лаконичный, надёжный и читаемый код. Кроме того, преподаватель оказался сильным разработчиком и автором одного из текстовых процессоров, так что это, разумеется, стало столь необходимым мне уроком смирения.
Я влюбился в OCaml. Он быстро стал моим основным языком программирования до выгорания, вызванного разработкой Opalang.
Взрыв мозга: программирование на уровне типов между модулями!
Сообщество OCaml по-прежнему очень активно. Он использовался в разработке языков программирования (в том числе и первых прототипов Rust), инструментов статического анализа для ядерных электростанций, операционных систем для космических спутников и других ситуаций, требующих чрезвычайно высокой степени безопасности. Кроме того, это один из непосредственных предков Rust, F#, Elm, ReasonML и, если память мне не изменяет, первой версии React. А, и ещё Opalang. По какой-то причине конкурентность передачи сообщений позиционируется сегодня как «gochannels», но, насколько я знаю, она берёт начало ещё в Concurrent ML, одном из предков OCaml.
Я начал изучать Java, когда пытался модернизировать код, написанный на Turbo Pascal, чтобы он мог работать в Linux, Windows и System 7 (предшественнице macOS). Этот язык показался мне многословным, я не мог понять, почему разработчики не поставляют установщик, учитывая сложность выпуска и/или запуска классов, и мне очень не хватало дженериков, алгебраических типов данных и сопоставления с образцом. Однако на долгое время Java стал моим базовым языком — не таким, на мой взгляд, хорошим, как OCaml, но с доступом к более качественным библиотекам.
Взрыв мозга: стандартная библиотека, в которой, похоже, есть всё необходимое мне!
Взрыв мозга: документация, которую писали так, чтобы она была понятна пользователям!
Если вы никогда не писали код на Prolog, то лишь рекомендую попробовать. Это полностью изменит ваше мышление о программах. В Prolog вы не пишете алгоритмы, а учите программу, как думать. Написать простой алгоритм поиска пути можно, задействовав примерно 2-4 тривиальных правила. Написание простой системы типов будет чуть длиннее.
Сегодня Prolog практически не существует. Однако его наследие огромно. Если память меня не подводит, SQL в большой мере основан на подмножестве Prolog с большим упором на оптимизацию в ущерб простоте. Система шаблонов C++ — это, по сути, более усложнённая реализация Prolog. Части системы типов Rust переписываются на Chalk — потомке Prolog.
Я подозреваю, что рано или поздно кто-нибудь начнёт комбинировать LLM с Prolog (или с Coq), чтобы создать поверх ChatGPT нечто надёжное. Кроме того, недавно я обнаружил TypeDB, очень похожий на новое поколение Prolog с API, напоминающим реляционные базы данных.
Coq (и его родственники Twelf, Isabel и так далее) — это нечто совершенно иное. Вы кодируете спецификации целиком, как типы. Эти типы и есть ваша цель.
Вы программируете не с помощью функций и библиотек, а используя инструменты для преобразования ваших типов, чтобы постепенно упрощать их в независимые подцели. Можно описать это так: вместо кодинга вы решаете головоломку. Разумеется, подцели в результате превратятся в ваши функции, в ваши структуры данных и модули. Но произойдёт это почти случайно.
И, разумеется… модуль контроля типов настолько мощен, что ваша программа — это, на самом деле, формальное, математически проверенное доказательство её соответствия спецификациям. Множество математических теорем было доказано благодаря превращению их в код на Coq.
Взрыв мозга: ожесточённые споры о том, какой же математик надёжнее, мозг или компьютер.
Я уже довольно давно не следил за разработкой Coq и других языков того же семейства. Насколько я понимаю, они довольно активно используются в научных кругах, где служат для формального доказательства соответствия спецификациям компиляторов и ядер операционных систем. Подозреваю, что если Prolog не вернётся, чтобы создать надёжные LLM, то кто-нибудь использует для этого Coq или Idris.
Erlang (а теперь и Elixir) был и остаётся лучшим языком для распределённых систем. Ядро гораздо проще, чем у Python, но легко масштабируется на миллионы узлов.
Взрыв мозга: тривиальная реализация распределённых систем.
Взрыв мозга: развёртывание нового кода из языка отправкой замыканий.
Хотя многие всё ещё не слышали о Erlang/Elixir, этот язык использовался в отрасли начиная с 90-х в высокораспределённых системах. Его экосистема вполне жива, сейчас тестируется система статических типов. Модель let it fail применяется в мобильных операционных системах. Конкурентность и модели распределения распространились на Scala, Go и практически на всё остальное, где есть слова «микросервисы» или «акторы». На самом деле, меня печалит, когда я вижу микросервисы или Kafka, ведь по большей мере это повторные реализации архитектуры Erlang/Elixir, а также их внутренней BEAM Virtual Machine, но основанные на технологиях, которыми гораздо сложнее пользоваться и разворачивать, а также на протоколах, которые на множество порядков медленнее.
О, да, и Opalang тоже позаимствовал кое-что у Erlang.
Здесь я сжульничал. Пи-исчисление — это не язык программирования, а исчисление, то есть математическая модель, спроектированная для рассуждений о системах. Эту модель можно полностью определить всего в десятке строк спецификации и очень легко реализовать. Она использовалась для выполнения статического анализа моделей криптографических протоколов, протоколов банкинга… а также биологических процессов. Я использовал её для определения системы типов, которую разработчики теоретически могли бы применять, чтобы гарантировать правильную деградацию своих протоколов в условиях (D)DoS-атаки.
Взрыв мозга: совершенно другой взгляд на условия гонки.
Взрыв мозга: полнота по Тьюрингу любого вида последовательной операции не нужна.
Взрыв мозга: описание сложных конкурентных/распределённых систем при помощи простой математики.
Я уже давненько не видел новых публикаций о пи-исчислении, но, возможно, просто не там смотрю.
Особый для меня случай, ведь я присоединился к команде и какое-то время был ведущим архитектором языка. Представьте, что вы пишете единую кодовую базу на простом функциональном языке + на основе акторов, сравнимом с OCaml/F#/ReasonML/Elm или с Erlang со статической типизацией, затем компилятор анализирует код на надёжность, безопасность и возможность распределённого использования, далее разделяет его на клиентский код (компилируемый в JavaScript + HTML + CSS), серверный код (компилируемый в нативное приложение) и код на стороне баз данных (компилируемый в схему базы данных и компилируемые запросы).
Я влюбился в этот язык. А затем выгорел, проектируя, разрабатывая и продвигая его в токсичном окружении. После этого мне понадобилось довольно много времени, чтобы вернуться в сферу проектирования языков программирования.
Взрыв мозга: автоматизированное разделение на клиент, сервер и базу данных.
Взрыв мозга: автоматическое устранение большинства проблем безопасности из Top 10 OWASP.
Взрыв мозга: автоматическое распределение между веб-серверами (хоть мы и немного это переусложнили).
Взрыв мозга: системы типов для анализа безопасности.
Взрыв мозга: асинхронные волокна (fibers) в JavaScript (до Promise, async/await и воркеров DOM).
Взрыв мозга: база данных, ориентированная на структуры данных.
Взрыв мозга: распределённая масштабируемая база данных (к сожалению, мы совершили ошибки, и на практике она оказалась довольно медленной).
Я считаю, что Opalang (и его родственники ReSharper и Ur/Web) был слишком большим прорывом для своего времени. Вся идея многоуровневого программирования, похоже, оказалась полностью забыта. Возможно, когда-нибудь она вернётся. WASM должен сильно упростить эту задачу.
Потом я влюбился в Rust. Он сочетал в себе многие преимущества OCaml и Haskell, обещая дать разработчикам возможность писать высококонкурентный код и выполнять разработку на уровне систем. Кроме того, на тот момент революционными идеями были модульная сборка мусора и планирование M:N, хоть от этих идей и отказались до версии 1.0. В то время я начал экспериментировать с языком, по большей мере это был исследовательский проект. Помню обсуждения обработки ошибок, строк и итераторов. Один из важнейших пунктов в моём резюме: я один из тех, кто внедрил идею макроса try!, который затем преобразовали в оператор ?.
Взрыв мозга: использование аффинных типов данных для доказательства свойств typestate.
Взрыв мозга: писать код, по производительности сравнимый с C++, но с гарантиями уровня OCaml.
Взрыв мозга: эффективная модель компиляции для async/await.
Взрыв мозга: то, насколько успешно система типов приводит к безопасным конкурентным решениям.
Взрыв мозга: дружелюбное и приветствующее новичков сообщество.
Взрыв мозга: частичная поддержка в написании моей собственной постепенной системы типизации (gradual type system).
У меня уже довольно долго не хватает времени, чтобы заниматься контрибьютингом в компилятор или stdlib, но когда оно найдётся, я планирую к этому вернуться!
К сожалению, мне кажется, Rust испортил для меня многие другие языки. Теперь когда я пишу на Python или Go (и тем, и другим я занимаюсь, чтобы зарабатывать на жизнь), или даже на TypeScript, мне всегда неприятна перспектива того, что мой код поломается, как только я его запущу. В Rust я кодирую в системе типов столько свойств, сколько могу, из-за чего перед написанием кода приходится немного дольше подумать, зато тесты обычно проходят с первого раза.
▍ А почему не $(ВАШ ЛЮБИМЫЙ ЯЗЫК)?
За свою карьеру я писал код на десятках языков программирования. В том числе на Haskell, Scheme, SmallTalk, (Tw)elf, Idris, Python, Go, PHP, Perl, Bash, C, C++, JoCaml,
JavaScript, TypeScript, Scala, C#, F#, Visual Basic, Ruby, (D)TAL, Squeak, Logo,
Scratch, UnrealScript, GDScript, Lua, SQL…
Если я не включил их в статью, значит, они не взорвали мой мозг. Это не значит, что эти языки не хорошие и не новаторские. Просто их концепция не вызвала во мне особого отклика или, что бывает чаще, я уже обнаружил те же концепции в каких-то других языках потому, что изучал их в таком порядке.
▍ Что дальше?
Я уже долгое время не видел ничего революционного, но это ничего не значит. Возможно, новая идея уже на подходе, где-то в небольшом исследовательском проекте, о котором я не слышал.
Когда я пришёл в PASQAL, то надеялся, что буду поражён языками для квантовых вычислений. Пока этого не случилось, но я не теряю надежды!
Мне кажется, что, несмотря на чрезмерный ажиотаж и безумный урон для окружающей среды, что-то полезное получится из ChatGPT и LLM, но пока не вижу этого. Я видел только интересные эксперименты, и многие игрушки уже кажутся поломанными. Любопытно, каким окажется будущее.
А какие языки повлияли на ваше мышление, связанное с программами?