Поколения Языков Программирования с точки зрения Инструментов Сознания

Feb 08, 2014 20:04


Этот пост является продолжением поста про инструменты сознания.

Можно рассмотреть развитие языков программирования в соответствии с внедрением инструментов сознания в области программирования.
Объекты и Шаги: Калькуляторы и Счеты

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

На этом уровне каждое действие немедленно меняет вычислительную систему.
Сочетания и Рецепты: ранний FORTRAN, ASM, и ранний BASIC

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

Набор типов был изначально зафиксирован (числа, символы, и массивы).

В более поздних версиях FORTRAN, и BASIC появились уже некоторые элементы последующих поколений. Но это уже не столь существенно для анализа. Современный ассемблер с развитой системой макросов, иногда тоже непонятно куда относить. Как ни странно, SQL тоже скорее принадлежит этому уровню.
Иерархии и Правила: Algol, C, Pascal, и Prolog

Мотивацию перехода на этот уровень можно почитать в этом разборе программной статьи «Go To Considered Harmful». Мне здесь нечего добавить.

На данном уровни появляются именованные правила (процедуры и функции), иерархическая структура блоков, и иерархические структуры данных (узлы: структура - поле). Пожалуй, первым таким языком был Algol.

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

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

Иногда Prolog пытаются отнести к языкам пятого поколения, но в рамках данного подхода, это третье поколение, причем без вариантов. С точки зрения динамики, у нас присутствуют правила, причем они именно так и называются. А с точки зрения структур данных, есть строго иерархические термы, где конечно можно организовать цикл (Х = а(Х)), но это скорее бага, а не фича, и при этом мы все равно получаем иерархию, только бесконечную. У языка Prolog даже нет нормальных ссылок на предикаты, можно сослаться на них только по имени, и нельзя стандартным образом частично указать состояние.
Модели и Метаправила: Java, C#, Haskell, и Scala

В это поколение было два разных захода, с разных сторон. Со стороны моделей, сюда пришли объектно-ориентированные языки. Со стороны метаправил, сюда пришли функциональные языки.

Исторически первыми были функциональные языки, и конечно же все началось с LISP-а. Нужно помнить, что этот язык программирования появился тогда, когда мейнстримом было второе поколение языков программирования. Это не мокло не сказаться на LISP-е, и таки сказалось.  В LISP-е можно определять функции, которые работают с функциями. Это каноничная форма метаправила. В языке С тоже можно использовать указатели на функции, но там функция всегда без состояния (дополнительные данные обычно передаются через указатель на void). С другой стороны, в LISP-е очень ограниченный набор типов данных, и нельзя определять свои типы, хотя по сравнению с FORTRAN был прогресс, так как можно было определять рекурсивные структуры данных. Есть конечно возможность использовать макросы, и с помощью них делались такие монстры как CLOS. Но это аналогично тому, как у вас бы забрали условный оператор, а взамен дали бы макросы и ассемблер (типа, пишите сами, как вам будет удобно). То есть, с точки зрения динамики язык был 4-ой стадии, на уровне типов данных это 2+ (фиксированный набор типов дает 2, а возможность построения произвольных графов, и сборка мусора - это небольшой элемент 4-ки). Несмотря на всю свою несбалансированность, язык до сих пор пользуется популярностью в узких кругах.

Следующую попытку достичь полноценного 4-ого поколения функциональные языки попробовали уже с учетом опыта 3-ого поколения (классическими представителями являются Haskell и ML). Кстати, есть ощущение, что основной задачей, которую решали создатели этих языков, это написание компиляторов, в языках есть куча вещей, которые удобны именно для этого, но вызывают проблемы при более приземленных задачах, вроде написания GUI библиотечки (да есть примеры таких библиотечек, о у меня они все вызывают ощущение противоестественности, достаточно простую задачу решают через одно место). В новом поколении функциональных языков появились именованные типы данных (и даже параметризованные), но эти структуры хорошо поддерживают ациклические графы, и плохо все остальное. ML, скрепя зубами, предоставляет тип Ref, для поддержки циклов в структурах данных, а Haskell даже этим не заморачивается, предоставляя только ленивые ссылки.

Объектно-ориентированные языки на эту стадию попали уже через модели. Первый объектно-ориентированный язык Simula 67, даже специально создавался под задачу моделирования. Нужно отметить, что объектно-ориентированное программирование можно осуществлять и на языках предыдущих поколений. Так, например, очень многие современные библиотеки GUI написаны на C и практически все они используют объектно-ориентированный подход к программированию (почти везде, где появляется необходимость работать с разными событиями одновременно, в том или ином виде появляется ООП в скрытом или явном виде). Потоки в Unix, тоже имеют признаки объектно-ориентированного подхода, а в microkernel архитектурах - ООП цветет и пахнет.

Объектно-ориентированные языки предоставляют конструкции, которые позволяют естественно реализовывать объектно-ориентированный подход к программированию. Для хорошей поддержки моделей, нужно уметь абстрагировать одну и туже логическую сущность разными способами в разных ситуациях, и как раз понятие интерфейса здесь помогает очень существенно. С появлением ООП, внезапно появились компоненты. Компоненты - это фактические модель полного желаемого поведения, и компоненты не реализуют желаемое поведение полностью самостоятельно, а работают вместе с контейнером. В качестве классических примеров можно привести EJB или CORBA. В некотором смысле, контейнер аналогичен функции, которая принимает другую функцию, а компонент - той функции которая передается в качестве аргумента.

Очень многие языки четвертого поколения поддерживают сборку мусора. А к тем, кто не поддерживает, все время пытаются либо частично автоматизировать процесс (например, автоматический подсчет ссылок), либо приделать относительно полноценный сборщик мусора сбоку (Boehm GC). Сборку мусора можно рассматривать как один из существенных признаков. Если структуры данных в основном иерархические, то более-менее понятно кто и за что отвечают, но когда появляются многочисленные горизонтальные связи в коде и структурах данных, то ответственность размывается, и без сборки мусора уже реально тяжело. Если объектно-ориентированные языки еще как-то держаться, то удачных попыток создать функциональный язык без сборки мусора, я даже не припомню.

Нужно отметить, что два разных подхода к созданию языков четвертого поколения уже сходятся. В объектно-ориентированные языки добавляются элементы функционального программирования (C#, Java 8, Scala, Groovy), а в функциональных языках появляются элементы объектно-ориентированного программирования (OCalm, Haskell (Type Classes)). Здесь я скорее ставлю на ООП языки, так они проектировались более прагматичными людьми, которые чаще сталкиваются с живым кодом.
Системный Уровень

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

IBM пропагандирует Autonomic Computing которая основывается на принципе обратной связи. Cloud Computing является выражением идеи системы, которая динамически адаптируется к отказам и к доступности ресурсов (например, GoogleFS и аналоги). Есть и другие проявления этого уровня в вычислительных технологиях.

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

много букв, развитие 2.0, программирование, психология

Previous post Next post
Up