Однажды мы с коллегами задумались вот о чём. Существует хронология языков программирования – список дат «с начала времён». Понятное дело, что каждый из них появился под влиянием собственных условий и для выполнения конкретных задач. Но ведь между языками есть тесные связи, и часто эти связи – эволюционные. А кто у нас главный по эволюции? Правильно – Чарльз Дарвин. Именно к его дню рождения 12 февраля мы и решили подготовить эту статью.

Подобная статья на Хабре уже есть, и она довольно интересная. Мы решили развить и дополнить тему. Для этого возьмём основные факторы эволюции, описанные в «Происхождении видов» Чарльза Дарвина, и попробуем провести параллели между эволюцией языков программирования и эволюцией живых существ.

Не воспринимайте эту статью слишком серьёзно. Это одна большая метафора, которая позволяет взглянуть на вещи под другим углом.

Наследственная изменчивость

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

И тут самое время вспомнить знаменитую диаграмму O’Reilly. Несмотря на то, что она заканчивается 2004 годом, на ней наглядно показано, как языки связаны между собой и кто чей потомок. Например, Python не был изобретён с нуля. В его основу легли наработки языка АBC, над которым ранее трудился «отец» Python Гвидо ван Россум. Из языка Modula-3 он заимствовал реализацию модулей и исключений. В нём можно встретить элементы Algol-68, C, C++, SmallTalk и др. В версии 2.0 появились list comprehensions, пришедшие из языков Haskell и SETL. И это только одна история. В прошлом других распространённых сегодня языков можно найти не меньше интересных предков. Но ведь и у предков была своя изменчивость. Например, тот же Modula-3 ведёт свою историю от Pascal.

Каждый из них в своё время соответствовал определённым требованиям, например:

  • отсутствие привязки к конкретной платформе;

  • простота для пользователей, отсутствие лишних деталей (их обработкой занимается машина);

  • возможность заметить и обработать ошибки в коде;

  • нефатальность ошибок для всей системы и др.

Соответствие языка подобным требованиям – знак его адаптивности к изменившимся условиям среды. Среди этих условий может быть что угодно: новые платформы, требования рынка, тренды в разработке и даже просто случайное стечение обстоятельств.

Так, например, насчёт происхождения языка C ходит несколько легенд. Согласно одной из них, Деннис Ритчи и Брайан Керниган любили играть в одну игру на сервере Bell Labs, которую потом понадобилось перенести на офисный компьютер. Для него пришлось написать операционную систему, но когда её стали переносить на другой компьютер, оказалось, что система написана на ассемблере. Это и сподвигло коллег создать высокоуровневый язык, позволяющий переносить ОС с одной машины на другую. Не знаем, имеет ли эта легенда что-то общее с реальностью, но это неплохая иллюстрация изменившихся условий среды. Возникла острая потребность – появился язык.

Естественный и искусственный отбор

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

Для современных проектов почти не используются такие языки, как COBOL, Algol, LISP, Pascal, Fortran, Ada и др. Причина их ухода в целом одна – они перестали отвечать современным требованиям. Например, COBOL был слишком сложным и требовал больших вычислительных мощностей, а также имел мало общего с синтаксисом прочих языков. А Pascal, несмотря на простоту освоения и удобство, проиграл в конкурентной борьбе C, который оказался более гибким языком, с большим количеством возможностей и приближённостью к железу.

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

Генная инженерия в этой области представлена новыми языками, призванными, по задумке авторов, исправить все негативные стороны предшественников.

В 2014 году компания Apple презентовала Swift. К слову об изменчивости, он вобрал в себя элементы C#, Python, Object-C, Haskell, CLU и некоторых других языков. Swift должен был ускорить и упростить разработку, быть быстрее (выше, сильнее и так далее) Objective-C. Но привело ли это к исчезновению последнего? Нет, он продолжает активно применяться, а изучать Swift начинающим часто рекомендуют не вместо, а вместе с Objective-C.

Ещё один пример – Dart от Google, который позиционировался как замена JavaScript ещё в 2011 году. Тут, думаем, даже и комментировать нечего. Открываем рейтинг языков программирования (например, этот, основанный на запросах) и видим Dart на 37-й позиции, тогда как JavaScript уверенно держится в десятке.

Борьба за существование

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

Конкурируют ли между собой разные языки программирования? Отчасти. Например, Python долгое время соперничал с С, Java и JavaScript... в рейтингах. В отчёте GitHub 2021 года он занимал вторую строчку. А в индексе TIOBE, составленном на основе данных поисковых запросов, в 2021 году он попал на третье место, к концу года сместился на второе, а в январе 2022-го занял верхнюю позицию. Другие рейтинги периодически удивляют новостями из серии «Древнейший язык программирования восстал из мёртвых» (статья 2021 года про Fortran, который на тот момент взлетел на целых 30 строчек вверх).

А что с внутривидовой борьбой? Признаем, что не совсем корректно называть разные версии Python одним «видом», так как их различия довольно существенны. Тем не менее, это стадии развития одного и того же языка, которые до определённого момента обладали обратной совместимостью. Переход с Python 2 на Python 3 был непростым для многих. Третья версия не полностью совместима с кодом, написанным на Python 2. И если проект живой и вносить изменения в код можно, то переход может вызвать затруднения, но, скорее всего, не станет камнем преткновения. Но в legacy-проектах, у которых есть только поддержка, переход может затянуться на годы. К счастью, большинство библиотек переписаны на Python 3, который в итоге всё же побеждает в борьбе.

Изоляция

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

Есть ли аналоги в программировании? Тоже да. Быстрое развитие смартфонов и смарт-часов создало такие изолированные «острова» для кода. В области мобильных приложений свою нишу, помимо Java, заняли Kotlin и Swift. Хотя их изоляция, конечно, условная. Например, Swift расширяет ареал: на нём уже можно писать приложения для Windows, macOS, Linux.

Критика дарвинизма

Параллели с развитием языков программирования можно провести не только между принципами дарвинизма, но и между некоторыми пунктами их критики.

Например, креационизм. Почему мы вообще говорим о каком-то развитии, если у большинства языков есть авторы? Джеймс Гослинг, Бьёрн Страуструп, Деннис Ритчи, Гвидо ван Россум когда-то действительно либо заложили основы, либо целиком описали их особенности. Но не стоит забывать, что эти люди – не теоретики. Они практикующие программисты, которые работали с разными языками на протяжении своей карьеры. Тот же Гослинг не планировал создавать новый язык во время работы в Green Project, а пробовал адаптировать для нужд проекта C++, но в конечном счёте сделать этого не получилось. Одной из основных особенностей языка должна была стать независимость от железа, поэтому Гослингу пришлось вспомнить о UCSD Pascal, который имеет такое свойство. И это просто один из примеров. Получается, что сферических творцов в вакууме не существует. Современные языки программирования так или иначе вобрали в себя элементы ранее существующих, переосмыслив их под новые требования и задачи.

Ещё один из аргументов противников дарвинизма состоит в том, что у живых существ есть чрезмерно сложные органы и системы (например, глаза). С одной стороны, не верится, что они могли возникнуть путём небольших случайных изменений, а с другой – непонятно, как они могли давать преимущество в борьбе за выживание на самых ранних этапах, когда самого органа ещё не было. И если уж мы проводим параллели, то программирование – неплохое доказательство того, что сложные структуры как раз и создаются путём мелких длительных изменений. Несмотря на то, что язык C++ – свободный, существует целая сложная система его стандартизации и соответствующий международный комитет. Стандарт обновляется с 1998 года, в последние годы значительно чаще. С 2016 года в России существует рабочая группа по развитию C++, которая собирает предложения по стандарту, организует их обсуждения, а также готовит материалы к защите в Комитете ISO C++. Собственное законодательство внутри одного языка – что может быть сложнее? Но это продукт его естественного развития, что видно по истории стандартов.

Кстати, Дарвин связан с программированием не только вот так опосредованно, но и напрямую. Его именем назван язык программирования – Darwin programming language. Он предназначен для биоинформатики и вычислительной биологии. Этот язык действует как своего рода калькулятор, помогающий обрабатывать данные о геномах биологических видов. Не знаем, насколько широко он сейчас используется, но название символичное.

Итог

Что мы хотели сказать этой статьёй? Что языки программирования – живые системы, которые формируются под воздействием среды. Что общие изменения языка определяются накоплением малых случайных изменений. Что в этих изменениях участвуют буквально все, кто работает с конкретным языком. И даже те, кто не работает напрямую – проджекты, дизайнеры, UX и CX, да и сами пользователи, наконец. Наверное, каждому стоит в качестве профилактики вспоминать об этом, когда после релиза весь отдел разгребает множество задач или когда мозг начинает плавиться от чужого кода.

Комментарии (23)


  1. forthuser
    12.02.2022 12:32
    +9

    И тут самое время вспомнить знаменитую диаграмму O’Reilly

    Развитие Forth (Форт), почему то заканчивается 87-м годом, что далеко неправда и даже принятие стандартов на язык не указано (79г, 84г, 94г.) ????

    Forth family tree
    image
    Forth Timeline
    image

    Источник данных диаграмм: Forth Family Tree and Timeline

    P.S. Хотя и эти диаграммы не полностью отражают текущую динамику появления новых подвидов Forth и близких ему идеалогически — конкатентивных языков, как Factor, 8th…

    Бейсиков и их диалектов, тоже не представили в диаграмме, хотя их и сейчас многое количество, и много книг по ним издано, хотя их большая часть и в прошлом, но от этого, что в них написано, менееинтересным они не становится.

    Мало представлено и ответвлений наследников функциональной парадигмы представленной в Lisp.


    1. gregorybednov
      12.02.2022 13:59
      +8

      Похоже, "форты" выбиваются из этой теории "эволюции", ведь сам факт рождения этого языка два раза - независимо Чарльзом Муром и Эдсгером Дейкстрой - уже ближе не к эволюции, а скорее к научному открытию, подобно изобретению радио Маркони и Поповым. (Пускай первый пришёл к Форту из практических соображений, а второй к форт-архитектуре пришёл скорее из теоретических сообщений)

      Самое интересное, что потомком Форта являются не только "форты", но и эзотерический FALSE, который фортом не является.

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


      1. me21
        12.02.2022 14:47
        +2

        Ну вот строение глаза человека и осьминога, по-моему, близко друг к другу, хотя развитие шло независимо. Вот тоже пример появления чего-то дважды.

        Опять же, в истории Земли можно найти происхождение новых классов, например, тех же млекопитающих, от животных, не вскармливавших детёнышей молоком.



  1. kichrot
    12.02.2022 13:22
    +4

    Хорошая и правильная статья, которая констатирует объективное, что теория эволюции Дарвина отражает самые общие закономерности развития объективной реальности (материи), в целом - существует только то, что может существовать в данных условиях, остальное не существует.

    Это и есть пресловутый естественный отбор, который действует абсолютно для всего, живого и неживого, в нашем бренном мире.

    Кстати, искусственный отбор, это форма естественного отбора, где человек выступает одним из факторов такого отбора.


  1. me21
    12.02.2022 14:48

    Креационизм здесь не возражение. Да, у языков были создатели, но частью эволюции языка можно считать эволюцию идеи в мозгу его автора.


  1. Sly_tom_cat
    12.02.2022 15:03

    Ну понятно что не очень серьезно. Но если проводить аналогии хотелось бы понять, а чему в живом мире может соотвествовать, например, COBOL?

    То есть, животное должно быть очень древним, давно утратившим возможность жить самостоятельно в изменившемся мире. Но на столько "полезным", что куча других видов (переодически сменя друг друга) завязываются в симбиотическую связь с этим древним, снижая тем самым риски для этого древнего вида быть тупо выеденным более бойкими и агрессивными видами, появившимися в современном мире?


    1. Jury_78
      12.02.2022 15:43
      -1

      Бактерии, вирусы...


      1. Sly_tom_cat
        12.02.2022 16:21

        Ну в микро-мире - дело понятное, а вот в мире макро-животных.... Ведь (опять же условность) но Дарвин строил свои теории именно по примерам мира макро-животных.

        Ну и потом микромир в ИТ это ИМХО "железо". Там то да транзистор до сих пор лежит в основе суперсовременных процессоров и других компонетнов.


        1. Jury_78
          12.02.2022 17:51
          +1

          Возьмите тогда вымерающие виды, некоторые, по моему, только в зоопарках сохранились.

          Ради разнообразия пытаемя сохранить.


          1. Sly_tom_cat
            12.02.2022 19:07
            +1

            Вот кстати да - подходящий вариант - зоопарк это как раз тот самый случай, когда животное уже не живет само по себе и выпущенное на свободу будет быстро съедено. При этом хозяева этого животного вполне могут меняться.


  1. GomboTs
    12.02.2022 15:47

    Безотносительно языков программирования, старик Дарвин определенно был прав.


  1. gregorybednov
    12.02.2022 16:15
    +7

    Не воспринимайте эту статью слишком серьёзно. Это одна большая метафора, которая позволяет взглянуть на вещи под другим углом.

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

    Сразу отмечу, что вывод, что большинство языков похожи на живые системы, вполне неплох, вполне соответствует материальной действительности. Остальные выводы также фактически верны, однако по-моему этого недостаточно - попробуем рассмотреть это подробнее.

    Что такое "среда, формирующая язык программирования"? Можно абстрактно сказать, что это "изменения, в которых участвуют буквально все", а можно прямолинейно сказать, что средой, формирующей язык программирования, является процесс разработки на этом языке, работа на этом инструменте. Откуда возникли перечисленные требования к "выживанию" языков программирования?

    * отсутствие привязки к конкретной платформе;

    * простота для пользователей, отсутствие лишних деталей (их обработкой занимается машина)

    * возможность заметить и обработать ошибки в коде

    * нефатальность ошибок для всей системы и др.

    А это ничто иное, как требования к разработке. Притом некоторые из них, по мнению "отцов-основателей" Computer Science, абсурдны, но они здесь перечислены: например, необходимым требованием к языку программирования названа "нефатальность ошибок для всей системы", которая противоречит принципам доказательного программирования, и вообще дейкстровскому "Если отладка — процесс удаления ошибок, то программирование должно быть процессом их внесения". Почему так получилось? Да потому что проще, просто дешевле производителю пользоваться языком, в котором ошибки рядового кодера нефатальны, чем математически доказывать корректность кода, или хотя бы писать код настолько иерархически определяя его и используя определения настолько кратко, насколько это вообще возможно (в том же Форте существует "правила хорошего тона", которые "не рекомендуют" использовать более 7 слов при определении нового слова - в результате приходится писать иерархии слов), и тут же проверять этот минимальный фрагмент на корректность.

    "Простота для пользователей, отсутствие лишних деталей" является справедливым требованием, абсолютная правда: однако "отсутствие лишних деталей" предполагает наличие неопределенности в системе (то есть сказав при решении какой-то задачи слово "медведь", ну как на иллюстрации в статье, мы не уточили, белый или бурый - значит, это либо не имеет значения, либо напрямую следует из контекста), а следовательно для неопределенности необходима поддержка трёхзначной логики. Таких возможностей нет у большинства рассмотренных языков, трехзначность там представлена в архитектуре языка неявно (хотя декларируется при этом, что в ЯП явное лучше скрытого). К слову, данное требование в совокупности с игнорированием семейств Лисп и Форт и их наследием, уже вовсе выглядит как издевательство: ведь именно в этих языках можно без проблем создать свои языковые конструкции специально под свою задачу (или даже написать свою особенную реализацию языка под свою задачу) и действительно не отвлекаться на "лишние детали" даже в виде стандартных операторов языков программирования; более того, возможности метапрограммирования позволяют вообще уйти от рутинного написания кода к его автогенерации.

    Однако такая простота находится в меньшинстве: ярким примером "простоты" для пользователя принято называть шаблоны C++, которые сами по себе являются ни много ни мало тьюринг-полным языком программирования. Простота нужна не для удобства программирования, не для ясности решаемой задачи, не для предотвращения внесения новых ошибок, а для максимально быстрого запихивания кода в прод при максимально возможно низкой квалификации кодеров - это та же проблема разработки.

    Что же касается первого требования (отсутствие привязки к конкретной платформе), то оно противоречит фактам; даже фактам, перечисленным в статье. "Быть ближе к железу" в отношении C, который перечислен как достоинство этого языка по отношению к Паскалю, это как раз близость языка C к конкретному железу, просто очень популярному и простому (если быть предельно точным, к компьютерам PDP-11). Паскаль же к тому моменту располагал P-кодом (portable), очень напоминающим виртуальную машину Java. Не сходится. В качестве другого примера отмечу, что ядро Linux в ранних его версиях критиковалось именно за четкую ориентацию на ранние архитектуры семейства x86. Так сложились обстоятельства, что в течение почти 10 лет бурного роста компьютерной техники (2000ые) x86 была по сути абсолютным монополистом.

    Почему C "уничтожил" Паскаль? В системном программировании виртуальные машины не очень пригодятся, а написание кода на "близком к железу" языке позволяет использовать больше вычислительных возможностей даже очень дешевых машин. C++ усугубил эту ситуацию, поскольку позволил писать на языке, близком к ассемблеру, прототипируя приложение на продажу в концепции ООП. При этом с точки зрения чистого ООП C++ не пользуется наверное ни одним преимуществом этого языка. Однако, он позволяет быстро разделить труд проектировщиков и кодеров, создавать программы не под конкретные задачи (которые постепенно усложняются), а под неопределенно широкий круг задач, создавать коммерческий софт, "софт как товар".

    Приведу пример: при автоматизации советского Госплана к каждому инженеру-расчётчику приходил программист, беседовал с ним о решаемых им задачах, создавал инструмент, который выполнял все рутинные операции, чтобы можно было перенаправить работника на иную, более сложную и творческую, работу в этом же направлении. 70% полученного кода - это решение задач уровня "эксель", 30% - это различные достаточно сложные операции, которые расчётчики в том числе могли производить с применением "инженерной прикидки" и так далее, которые не решаются экселем (в базовом владении данным инструментом). А другой путь - это как раз купить условный MS Office Excel, который в сущности и автоматизацией не является, просто позволяет нанять менее клафицированного сотрудника для решения тех же задач, на выполнение настолько же рутинных (если не более рутинных) действий, просто более простых. Собственно, если в "мёртвых" языках Lisp и Forth есть возможность метапрограммирования (генерации программ программами, чтобы как раз можно было уйти от "рутины программирования") изначально, то во всех потомках C++ (о которых и идёт речь далее) эта возможность прикручена как "костыль", т.к. она противоречит модели языка.

    Так и получается: если в 80-90ых написанный софт будет работать на слабеньких PC, то его закупят. А если софт при этом окажется на рынке раньше всех и он будет не настолько плох, чтобы от него отказывались, то он завоюет рынок. Так что это не C++ и его потомки победили всех остальных потому что "крутой язык", это компании которые практиковали С++/потомки C++ выкупили всех остальных. А дальше эту ситуацию уже можно заменять фразой "так сложилось исторически", не рассматривая произошедшего.

    Я это к чему: эволюция языков программирования безусловно есть. Проблема в том, что большей частью отбор происходит не по объективным свойствам того или иного языка, а по требованиям к процессу разработки, по существующей конъюнктуре рынка софта и рынка IT-труда. Язык (или компьютерная архитектура - такое произошло, например, с легендарной "Сетунью" и массой других проектов советской школы микроэлектроники, убитых стандартизацией советской микроэлектроники по IBM - лидеру американского рынка) может обладать впечатляющими возможностями, быть достаточно удобным для разработчиков и прочих пользователей, но тупо "не вписаться". А потом люди будут писать, что технология X просто "обогнала время" и должна была появиться позже. Нет, она появилась скорее всего когда надо, просто прогресс в этой технологической области был предельно заторможен, пока "происходила вроде как эволюция, велись скрещивания, ..."


    1. lucius
      12.02.2022 22:07

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

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


    1. 0xd34df00d
      12.02.2022 23:07
      +1

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

      Каким образом это следует и зачем она необходима?


      Почему неопределённость медведя не может быть проинтерпретирована в зависимости от контекста и конкретной формулировки либо как верность для всех медведей, либо как существование медведя, для которого это верно?


    1. third112
      12.02.2022 23:57

      Так что это не C++ и его потомки победили всех остальных потому что "крутой язык", это компании которые практиковали С++/потомки C++ выкупили всех остальных.

      К этому можно добавить, что MS сильно обиделась на Borland, когда ОО Pascal MS оказался неудачным, а у Borland — удачным. MS забросила Pascal.


  1. Alvot333
    12.02.2022 19:47

    Диаграммы Эйлера-Венна – геометрическое представление множеств.


     

     

     

     

     


  1. Amomum
    13.02.2022 04:46

    Мне вот интересно, не пора ли уже включать yaml в список языков программирования?

    Глядя на то, как его гоняют в хвост и в гриву всякие кубернетесы и хельмы, собирая те же грабли, на которые традиционные ЯП уже наступали, мне становится грустно..


    1. allter
      13.02.2022 15:33

      yaml - это не язык программирования (но язык). Как и S-expression, это просто язык для описания синтаксического дерева. Конкретные виды этих деревьев - это, в свою очередь, языки программирования.


  1. umnic
    13.02.2022 12:46
    +1

    Я не могу понять — каким образом пример интиллигентного дизайна может служить аргументом в пользу теории эволюции?

    Развитие языков прораммирования — это развитие в результате разумной целенаправленной деятельности.

    Аргументом в подтверждение теории эволюции могло бы стать появление нового ЯП целиком и полностью за счет ошибок документирования и копирования.


  1. fimble
    13.02.2022 15:55

    Напомнило аллегорию из всем известного учебника...


  1. Bedal
    13.02.2022 16:25

    Во все эти игры с похожестью и биологическими аналогиями нужно включить параллельный перенос генов. Тогда много станет на свои места и не нужно будет столько натяжек.
    В целом же эволюция ЯП — вполне себе эволюция мемов, да. Но тут уже нужно рассуждать не в базовых терминах естественного отбора (которые, кстати, привлечены не полностью и потому некорректно), а рассуждения Докинза о мемах.


  1. AmigoRRR
    14.02.2022 15:01

    Не раскрыта тема языка RUST, это как раз осмысленная эволюция того же C++.