Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

«Классификация языков программирования высокого уровня» _

Содержание:

ВВЕДЕНИЕ

Прогресс компьютерных технологий определил процесс появления новых разнообразных знаковых систем для записи алгоритмов – языков программирования. В настоящее время известно более 8000 языков программирования [15]. В настоящее время в мире существует несколько сотен реально используемых языков программирования. Для каждого есть своя область применения. Каждый год их число пополняется новыми языками. Некоторыми языками умеет пользоваться только небольшое число непосредственных разработчиков, другие языки становятся известными миллионам людей. Профессиональные программисты иногда применяют в своей работе более десятка разнообразных языков программирования.

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

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

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

В связи с этим тема курсовой работы особенно актуальна.

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

Для достижения данной цели в работе поставлены следующие задачи:

  1. Изучить понятие и развитие языков программирования.
  2. Выявить особенности языков программирования высокого уровня.
  3. Рассмотреть такие процедурные и непродурные виды языков программирования высокого уровня.
  4. Провести классификацию языков программирования высокого уровня по уровню специализации.
  5. Дать характеристику таких непроцедурных языков программирования высокого уровня как функциональные, логические иобъектно-ориентированные языки программирования.

Объектом исследования являются языки программирования высокого уровня.

Предмет исследования – классификация языков программирования высокого уровня.

При написании работы были использованы учебники и учебные пособия, монографии, материалы научных конференций, сети Интернет.

Наиболее надежными источниками можно считать монографии, учебники и учебные пособия, в том числе и электронные. Они изданы известными издательствами, например, Издательство Юрайт, Питер, Вильямс и др., а также вузами, такими как УлГТУ, СибГУТИ, НГТУ и др.

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

Менее надежными являются материалы, размещенные в сети Интернет, однако, как уже было отмечено. Это или электронные учебные пособия вузов, или статьи и лекции, среди авторов которых ученые кандидат технических наук, доцент Соколов В.В., профессор Бекман И. Н. и т.д.

1. ПОНЯТИЕ ЯЗЫКА ПРОГРАММИРОВАНИЯ ВЫСОКОГО УРОВНЯ

1.1. Понятие языка программирования. Эволюция развития языков программирования

Язык программирования – искусственный (формальный) язык, предназначенный для записи алгоритмов. Он отличаются от естественных ограниченным, достаточно малым числом слов, значение которых понятно транслятору, и очень строгими правилами записи команд (предложений). Совокупность правил, определяющих допустимые конструкции (слова, предложения) языка, т.е. его форму, образуют синтаксис языка, а совокупность правил, определяющих смысл синтаксически корректных конструкций языка, т.е. его содержание, – семантику языка [10, с.7].

Нарушения формы записи конструкций языка программирования приводят к синтаксическим ошибкам, а ошибки, связанные с неправильным содержанием действий и использованием недопустимых значений величин, называются семантическими. Логические ошибки возникают, когда все конструкции языка записаны правильно, но последовательность их выполнения дает неверный результат [17].

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

  • машинные;
  • машинно-оpиентиpованные (ассемблеpы);
  • машинно-независимые (языки высокого уровня) [8, с.405].

Рассмотрим кратко историю развития языков программирования от низкого к высокому уровню.

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

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

Затем возникла идея использовать при записи вместо неудобных и трудных для запоминания кодов мнемонические обозначения команд, после чего специальные люди-кодировщики по таблицам соответствия переводили программу в машинный код. Большой скачок в программировании произошел, когда машине доверили выполнение такого перевода с помощью специальной системной программы (ассемблера). Кроме того, стало возможно обозначать ячейки не конкретными адресами в памяти (фактически, номерами ячеек), а символическими именами и потом ссылаться на них в программе [18].

Язык ассемблера – это машинно-зависимый язык низкого уровня, в котором короткие мнемонические имена соответствуют отдельным машинным командам. Термин ассемблер произошел от английского слова assembler, так называли сборщик частей в одно целое, в данном случае - сборщик программы. Процесс сборки называется ассемблированием. Язык ассемблера отнесем ко второму поколению языков программирования [15].

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

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

Итак, в группу языков низкого уровня входят машинные языки и языки символического кодирования: (Автокод, Ассемблер) [4, с.19].

Очередная революция в языках программирования произошла в 50-х г.г. ХХ в., когда появились языки программирования высокого уровня или третьего поколения. В них характерные для машины понятия, такие как ячейки памяти или простейшие операции суммирования чисел в ячейках памяти, заменялись абстрактными переменными и довольно сложными выражениями, похожими на используемые в математике формулы (неудивительно, что первый язык программирования высокого уровня так и назвали - Фортран, от слов «формульный транслятор»).

При создании языков высокого уровня делалась попытка выразить в языке суть алгоритма решения задачи, абстрагированного от мелких деталей реализации на той или иной ЭВМ, что нашло свое отражение в названии еще одного знаменитого языка программирования - Алгол (от англ. algorithmic language - алгоритмический язык) [10, с.20].

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

К языкам высокого уровня относятся Фортран, Алгол, Кобол, Паскаль, Бейсик, Си, Пролог и т.д. Эти языки машинно-независимы, так как они ориентированы не на систему команд той или иной ЭВМ, а на систему операндов, характерных для записи определенного класса алгоритмов. Отметим, что ряд авторов выделяют и языки сверхвысокого уровня. Повышение уровня таких языков произошло за счет введения сверхмощных операций и операторов [14].

Основные преимущества алгоритмических языков программирования перед машинными и машинно-ориентированными языками:

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

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

Нужно отметить, что операторы и ключевые слова новых языков программирования были более осмысленны, чем безликие цифровые последовательности кодов, что также обеспечивало повышение производительности труда программистов [3, с.9].

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

1.2. Общие особенности языков программирования высокого уровня

Машино-независимые языки – средство описания алгоритмов решения задач и информации, подлежащей обработке. Они удобны в использовании для широкого круга пользователей и не требуют от них знания особенностей организации функционирования ЭВМ и ВС [19].

Большинство программистов пользуются для составления программ языками высокого уровня. Как и обычный человеческий язык, такой язык имеет свой алфавит – множество символов, используемых в языке. Из этих символов составляются так называемые ключевые слова языка. Каждое из ключевых слов выполняет свою функцию, так же как в привычном нам языке слова, составленные из букв алфавита данного языка, могут выполнять функции разных частей речи. Ключевые слова связываются друг с другом в предложения по определённым синтаксическим правилам языка. Каждое предложение определяет некоторую последовательность действий, которые должен выполнить компьютер [2, с.136].

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

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

Рисунок 1 – Структура языков программирования высокого уровня [6, с.16]

Язык высокого уровня выполняет роль посредника между человеком и компьютером, позволяя человеку общаться с компьютером более привычным для человека способом. Часто такой язык помогает выбрать правильный метод решения задачи. Перед тем как писать программу на языке высокого уровня, программист должен составить алгоритм решения задачи, то есть пошаговый план действий, который нужно выполнить для решения этой задачи. Поэтому языки, требующие предварительного составления алгоритма, часто называют алгоритмическими языками [17].

Как было уже сказано, для того чтобы программу можно было использовать на некоторой ЭВМ (с произвольной системой команд), достаточно было наличия для нее транслятора (программы-переводчика) с соответствующего языка высокого уровня в машинный код.

Рисунок 2 – Схема работы транслятора [18]

При наличии трансляторов для разных архитектур теоретически становится возможным написать и отладить программу на одной ЭВМ, а затем перенести ее на другую и там использовать. Естественно, к минусам данной технологии можно отнести необходимость предварительной разработки транслятора [18].

Транслятор может относиться к одной из двух разновидностей: компиляторы и интерпретаторы. Разница между ними заключается в следующем. Компилятор принимает на вход всю программу на языке высокого уровня целиком и в результате процесса трансляции строит так называемый объектный модуль, содержащий машинный код, понятный процессору целевой ЭВМ. Интерпретатор переводит программу на языке высокого уровня построчно, при этом для каждой строки исходной программы создает некоторое внутреннее представление на специальном промежуточном языке, которое направляется специальной машине времени исполнения, или виртуальной машине (Virtual Machine). Эта машина немедленно исполняет полученное предписание [13, с.21].

И у компиляторов, и у интерпретаторов есть достоинства и недостатки. К достоинствам компилятора относится в первую очередь то, что полученный машинный код может непосредственно исполняться на данной ЭВМ, при этом наличия компилятора в момент выполнения не требуется. Выполнение же происходит на максимально возможной скорости. Однако в случае необходимости внесения в программу изменения, даже минимального, потребуется произвести перекомпиляцию исходного текста полностью, даже если он насчитывает десятки тысяч строк [18].

Интерпретатор переводит программу построчно, поэтому он удобен для отладки программы, когда постоянно происходят уточнения и изменения и нужно быстро увидеть, как поведет себя откорректированная программа. К недостаткам интерпретатора относится то, что, поскольку программа исполняется интерпретатором, а не непосредственно процессором, во-первых, скорость выполнения программы существенно ниже, чем при компиляции (обычно в 10–20 раз), а во-вторых, требуется наличие машины времени выполнения в памяти [13, с.21].

В то же время скомпилированная программа в машинном коде - аналогично программе на ассемблере - может исполняться лишь на архитектурно совместимой ЭВМ. А для интерпретируемого языка (например, Java) достаточно установки на данный компьютер машины времени исполнения (в случае Java - JVM (Java Virtual Machine)), после чего на ней теоретически могут быть исполнены любые программы на данном интерпретируемом языке.

Среди языков программирования высокого уровня Бейсик, Лисп, Java, Питон, Форт обычно реализуются как интерпретаторы, а Фортран, Си, С++, Паскаль, Модула-2 - как компиляторы, хотя это правило не является обязательным [13, с.22].

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

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

2. ВИДЫ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ ВЫСОКОГО УРОВНЯ

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

Рисунок 3 - Классификация языков программирования [9, с.16]

Заметим, что языки программирования довольно сильно различаются между собой в зависимости от используемых базовых теоретических положений — так называемой модели вычислений. По данному основанию машинно-независимые языки делятся на процедурные, иногда называемые операторными или императивными, и непроцедурные (отметим, что среди процедурных языков есть и языки низкого уровня) [5, с.168].

2.1. Процедурные языки программирования

Исходя из того, что программа, по сути, представляла собой набор директив, обращенных к компьютеру, такой подход к программированию получил название императивного (процедурного). Эти предписания в ассемблере принято называть командами, а в языках высокого уровня - операторами. Фрагмент программы может выглядеть следующим образом:

<оператор1>

<оператор2>

<оператор3>

<операторn> [13, с.34].

В некоторых языках программирования операторы нумеруются.

Таким образом, императивные языки описывают процесс вычислений в виде команд, изменяющих состояние программы. Эти языки разрабатывались для фон-неймановской архитектуры ЭВМ, названной так в честь её автора – Джона фон Неймана. В компьютере фон Неймана данные и программы хранятся в одной и той же памяти, называемой оперативной. Центральный процессор получает из оперативной памяти очередную команду, декодирует её, выбирает из памяти указанные данные, выполняет команду и возвращает в память результат [10, с.8].

Основными элементами императивных языков являются переменные, моделирующие ячейки памяти ЭВМ; операторы присваивания, осуществляющие пересылку данных; один или несколько итеративных циклов. При этом программа может структурироваться на меньшие части - подпрограммы, которые называются функциями, процедурами или классами в зависимости от языка. Каждая подпрограмма, в свою очередь, имеет свое собственное имя, начало и конец [3, с.19].

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

Процедурное программирование дает возможность повторного использования кода и в некотором смысле реализует принцип матрешки. Процедура - блок, который раскрывается в другом месте, а из данной программы лишь вызывается (указанием ее имени) [2, с.214].

Примером данного вида языков является язык Fortran (FORmula TRANslation) – язык программирования высокого уровня, разработанный фирмой IBM в 1956 году для описания алгоритмов решения вычислительных задач. Весьма любопытно, что Фортран жив и успешно используется до сих пор, например, в научных расчетах — конечно, развиваясь и вбирая новшества в программировании (были выпущены стандарты Фортран 77 и Фортран 90). Объясняется это, в частности, большим объемом наработанных эффективных библиотек программ, которые нет смысла переписывать на другие языки, но не только этим - например, в язык изначально встроена поддержка комплексных чисел, чего нет во многих современных языках. Последние версии Фортрана используются для программирования компьютеров с параллельной архитектурой [16].

Одним из наиболее известных, сильно повлиявших на дальнейшее развитие информационных технологий и широко используемых до сих пор языков программирования является Си (C) – язык программирования высокого уровня, разработанный Денисом Ритчи в начале 1970-х годов. На его основе были созданы такие наиболее популярные в настоящее время в индустрии программирования языки, как С++, С#, Java, PHP, Objective C и др. [16].

Кобол (COBOL, COmmon Business-Oriented Languauge) – язык программирования высокого уровня, разработанный в конце 1959-х гг. ассоциацией КАДАСИЛ для решения коммерческих и экономических задач. Отличается развитыми средствами работы с файлами. Поскольку команды программ, написанных на Коболе, используют обычную английскую лексику и синтаксис, язык считался одним из самых простых. В настоящее время практически не используется [19].

Алгол (ALGOL, ALGOrithmic Language) - язык программирования высокого уровня, ориентированный на описание алгоритмов вычислительных задач. Был создан в 1958 году специалистами западно-европейских стран для решения научных задач. Версия этого языка Алгол-60 была принята Международной конференцией в Париже и получила широкое распространение. Версия Алгол-68, разработанная группой специалистов Международной федерации по обработке информации в 1968 году, получила статус международного универсального языка программирования, ориентированного на решение не только вычислительных, но и информационных задач. Хотя этот язык не получил широкого распространения, он долгие годы являлся стандартом для описания алгоритмов в научной литературе [19].

Бейсик (BASIC, Beginner`s All-purpose Symbolic Instruction Code) – язык программирования высокого уровня, разработанный в 1963–1964 годах в Дартмутском колледже Томасом Куртом и Джоном Кемени. Первоначально предназначался для обучения программированию. Отличался простотой благодаря наличию упрощенных конструкций языка Фортран и встроенных математических функций. В большинстве версий Бейсика используется интерпретатор для преобразования конструкций языка в машинный код, что позволяет запускать программы без промежуточной трансляции.

Паскаль (PASCAL, Program Applique a la Selection et la Compilation Automatique de la Litterature) – французский язык программирования высокого уровня, разработанный в конце 1960-х годов швейцарским профессором, ставшим Нобелевским лауреатом, Никласом Виртом. Язык предназначался для первоначального обучения программированию в университете. Назван в честь французского математика XVII века Блеза Паскаля [19].

К этому виду языков относятся также такие распространённые языки программирования, как: PL/1, Ada, Java и др. Время появления отдельных императивных языков показано на рис.4.

Рисунок 4 – Императивные языки программирования [20]

Отметим, что внутри процедурной парадигмы можно выделить структурное программирование, которое не выходит за рамки этого направления, оно лишь использует полезные приемы программирования (структурная запись программы, отказ от оператора перехода, составные операторы или блоки), что делает программистскую деятельность более производительной и защищенной от ошибок и путаницы в программах [9, с.19].

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

2.2. Непроцедурные языки программирования

Принципиально иные направления в программировании относятся к непроцедурным парадигмам. К ним можно отнести объектно-ориентированное и декларативное программирование [11, с.128].

В 60-х г.г. ХХ в. возникает новый подход к программированию, который до сих пор успешно конкурирует с императивным, а именно, декларативный подход.

Декларативный подход к программированию означает, что с программиста снимается обязанность подробного инструктирования ЭВМ, как именно решать задачу (пошагового описания алгоритма), вместо чего ему необходимо лишь выполнить постановку задачи некоторым формальным образом, задав существующие ограничения, то есть описать, что требуется получить в качестве результата. Происходит переход от «Как?» к «Что?» [21].

Декларативный подход является попыткой воплощения идеальной технологии программирования, в качестве которой может быть рассмотрена такая технология, когда по некоторому довольно неформальному описанию задачи автоматически генерируется синтаксически и семантически корректная программа решения. Поиск решения при этом возлагается на встроенную в систему программирования «машину вывода». Ярким примером декларативного подхода являются и языки семейства SQL – языки запросов к базам данных, в которых описывается, что нам надо извлечь из базы, а система управления базой данных сама осуществляет все необходимые для этого действия [21].

Еще одно достоинство декларативных языков - пригодность для формальных рассуждений, которые, в частности, могли бы поднять методы обеспечения надежности и безошибочности в программировании на новый уровень (известно, что тестирование может помочь обнаружить ошибки в программах, но не может гарантировать их отсутствия). К сожалению, существующие методы формального анализа программ чрезвычайно трудоемки. Много усилий было направлено на создание более простых и строгих языков, а также совершенствование методов анализа, но результаты не обнадеживают [12, с.336].

Декларативная программа обладает также следующим преимуществом. Она может быть подвергнута логическому анализу в своих собственных понятиях, для чего не требуется привлечение дополнительных формализмов, таких как предикаты на состояниях. Более того, возникает возможность создания инструментальных средств, позволяющих автоматизировать процессы анализа, преобразования и синтеза программ. Появление таких средств может в корне изменить программирование. При программировании на традиционном (императивном) языке у программиста нет иного выбора, кроме как вникать в низкоуровневые подробности выполнения программ. В декларативных языках логика и управление отделены друг от друга. Декларативную программу проще написать и, что немаловажно, проще понять, чем эквивалентную императивную программу. Помимо этого возникает возможность переложить ответственность за реализацию порядка выполнения операций на компьютер. Более того, становится возможным использовать нетривиальные алгоритмы планирования вычислений, такие как недетерминированные, «ленивые» и параллельные подходы [7, с.94].

На начальном этапе развития декларативным языкам программирования было сложно конкурировать с императивными в силу объективных трудностей при создании эффективной реализации трансляторов. Программы работали медленнее, однако, они могли решать с меньшими трудозатратами более абстрактные задачи. В частности, язык SML был разработан как средство доказательства теорем [21].

Наиболее распространённым декларативным языком является язык Prolog. Основными областями его применения являются экспертные системы, системы обработки текста на естественных языках и системы управления реляционными базами данных. Различные диалекты языка LISP, возникли потому, что ядро и идеология этого языка оказались весьма эффективными при реализации символьной обработки (анализе текстов). Другой характерный пример декларативных языков программирования - Haskell [14].

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

Важным шагом на пути к совершенствованию языков программирования стало появление в 1970-х гг. объектно-ориентированного подхода к программированию и соответствующего класса языков. Наиболее ранними объектно-ориентированными языками программирования стали Simula 67 и Smalltalk; примерами более поздних объектно-ориентированных языков программирования являются C++, С#, Java и др. В основе этих языков лежит понятие объекта, сочетающего в себе данные и действия над ними. Описание действительности в форме системы взаимодействующих объектов естественнее, чем в форме взаимодействующих процедур [19]. Данный вид программирования также будет рассмотрен в главе 3.

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

Отметим, что в функциональном программировании высший приоритет отдается понятию функции и предполагает жесткое структурирование данных (последовательность последовательностей), что создает сложности для представления привычных для программистов данных в виде массивов, записей и тому подобных структур данных. В свою очередь, логическое программирование акцентирует внимание на средствах логики. Но эти средства ограничены возможностями чисто декларативных логик. В результате была сделана попытка объединения логического программирования с функциональным. Примером такого подхода является создание языка Логлисп, который реализует парадигму логического программирования в рамках языка Лисп [5, с.171].

2.3. Классификация языков программирования высокого уровня по уровню специализации

С расширением областей применения вычислительной техники возникла необходимость формализовать представление постановки и решение новых классов задач. Необходимо было создать такие языки программирования, которые, используя в данной области обозначения и терминологию, позволили бы описывать требуемые алгоритмы решения для поставленных задач, ими стали проблемно – ориентированные (специализированные) языки [2, с.98].

Проблемно-ориентированные (или предметно-ориентированные) языки программирования (англ. DSL - Domain Specific Language) подразумевают, что в языке наряду с универсальными управляющими конструкциями и типами данных присутствуют встроенные средства для описания понятий, характерных для конкретной предметной области, для решения задач которой предназначается данный язык. Предметно-ориентированные языки программирования используются в различных сферах — атомной энергетике, космических исследованиях, радиотехнике и пр.

Проблемных языков очень много, например: Фортран, Алгол – языки, созданные для решения математических задач; Simula, Слэнг - для моделирования; Лисп, Снобол – для работы со списочными структурами [2, с.99].

Весьма популярны встроенные проблемно-ориентированные языки в мощных информационных системах. Яркий пример - системы автоматизации управления предприятием, в которых поддерживаются такие понятия, как документ, бухгалтерский счет, проводка и пр. Встроенный язык программирования системы SAP/R3 называется ABAP, язык белорусской системы «Галактика» - VIP, есть свой язык в известном в нашей стране пакете 1C. Система автоматизации проектирования AutoCAD позволяет писать дополнительные приложения на специально адаптированной версии языка программирования Лисп - AutoLiSP. В системе управления базами данных Oracle для написания программ применяется язык PL/SQL. Все это позволяет значительно быстрее и удобнее создавать прикладные программы и повысить качество разработки [13, с.43].

Универсальные языки были созданы для широкого круга задач: коммерческих, научных, моделирования и т.д. Первый универсальный язык был разработан фирмой IBM, ставший в последовательности языков Пл/1. Второй по мощности универсальный язык называется Алгол-68. Он позволяет работать с символами, разрядами, числами с фиксированной и плавающей запятой. Пл/1 имеет развитую систему операторов для управления форматами, для работы с полями переменной длины, с данными организованными в сложные структуры, и для эффективного использования каналов связи. Язык учитывает включенные во многие машины возможности прерывания и имеет соответствующие операторы. Предусмотрена возможность параллельного выполнение участков программ. Программы в Пл/1 компилируются с помощью автоматических процедур. Язык использует многие свойства Фортрана, Алгола, Кобола [2, с.9101].

Здесь отметим, что языки четвёртого поколения – это именно языки программирования, разработанные для специализированных областей применения, где хороших результатов можно добиться, используя не универсальные, а проблемно-ориентированные языки, оперирующие конкретными понятиями узкой предметной области. Все языки программирования четвёртого поколения разработаны для снижения временных затрат на разработку программ. К четвёртому поколению обычно относят: языки запросов к базам данных (SQL, Informix-4GL и т.д.), языки обработки данных (Visual DataFlex, FoxPro, XBase++ и т.д.), а также средства генерации программного кода на языках третьего поколения, встраиваемые в системы программирования [13, с.44].

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

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

Также языки программирования принято делить на проблемно–ориентированные (специализированные) и универсальные языки.

3. ХАРАКТЕРИСТИКА НЕПРОЦЕДУРНЫХ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ ВЫСОКОГО УРОВНЯ

3.1. Функциональные языки программирования

Одним из путей развития декларативного стиля программирования стал функциональный подход, возникший с появлением и развитием языка LISP. На практике наибольшее распространение получили и два его диалекта: Common Lisp и Scheme [3, с.14].

LISP (LISt Processing) – язык программирования высокого уровня, разработанный в 1960 году Джоном Маккарти и предназначенный для манипулирования перечнями элементов данных. Использовался в университетских лабораториях США для решения задач, связанных с искусственным интеллектом. Основной структурой данных языка функционального программирования Lisp являются связные списки, элементами которых могут быть либо идентификаторы и числовые константы, либо другие связные списки. Областью применения этого языка являются системы искусственного интеллекта.

Другими известными языками функционального программирования являются ML, Miranda, Erlang и Haskell и др. Время появления отдельных функциональных языков показано на рис.5.

Рисунок 5 – Функциональные языки программирования [20]

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

Функциональное программирование не использует концепцию памяти как хранилища значений переменных. Операторы присваивания отсутствуют, вследствие чего переменные обозначают не области памяти, а объекты программы, что полностью соответствует понятию переменной в математике. Наличие стройной математической основы обеспечивает возможность использования алгебраических методов создания структуры, преобразования и исследования программ. Это в какой-то мере приближает их к описанию структуры мышления человека [21].

Сложные программы при таком подходе строятся посредством агрегирования функций. Разработка программы заключается в создании из простых функций более сложных, которые последовательно применяются к начальным данным до тех пор, пока не получится конечный результат. При этом текст программы представляет собой функцию, некоторые аргументы которой можно также рассматривать как функции. Таким образом, повторное использование кода сводится к вызову ранее описанной функции, структура которой, в отличие от процедуры императивного языка, прозрачна математически [21].

Более того, типы отдельных функций, используемых в функциональных языках, могут быть переменными. Таким образом обеспечивается возможность обработки разнородных данных (например, упорядочение элементов списка по возрастанию для целых чисел, отдельных символов и строк) или полиморфизм [3, с.27].

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

Таким образом, при создании программ на функциональных языках программист сосредотачивается на области исследований (предметной области) и в меньшей степени заботится о рутинных операциях (обеспечении правильного с точки зрения компьютера представления данных, «сборке мусора» и т.д.) [10, с.8].

Поскольку функция является естественным формализмом для языков функционального программирования, реализация различных аспектов программирования, связанных с функциями, существенно упрощается. В частности, интуитивно прозрачным становится написание рекурсивных функций, т.е. функций, вызывающих самих себя в качестве аргумента. Кроме того, естественной становится и реализация обработки рекурсивных структур данных (например, списков – базовых элементов, скажем, для семейства языков LISP) [21].

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

Естественно, языки функционального программирования не лишены недостатков. Часто к ним относят нелинейную структуру программы и относительно невысокую эффективность реализации. Однако, первый недостаток достаточно субъективен, а второй успешно преодолен современными реализациями, в частности, рядом последних трансляторов языка SML, включая и компилятор для среды Microsoft .NET [21].

3.2. Логические языки программирования

В 70-х г.г. возникла еще одна ветвь языков декларативного программирования, связанная с проектами в области искусственного интеллекта, а именно, языки логического программирования. Иногда к таким языкам применяют термин «языки пятого поколения» (однако это не является общепринятой точкой зрения).

В качестве примеров языков логического программирования можно привести Prolog и др. Prolog (PROgramming in LOGic) – язык программирования высокого уровня, предназначенный для разработки систем и программ искусственного интеллекта. Был разработан в 1971 году в университет Марселя [8, с.406].

Время появления отдельных логических языков показано на рис.6.

Рисунок 6 – Логические языки программирования [20]

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

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

Таким образом, языки логического программирования базируются на классической логике и применимы для систем логического вывода, в частности, для так называемых экспертных систем. На языках логического программирования естественно формализуется логика поведения, и они применимы для описаний правил принятия решений, например, в системах, ориентированных на поддержку бизнеса [1, с.31].

Важным преимуществом подхода является достаточно высокий уровень машинной независимости, а также возможность откатов – возвращения к предыдущей подцели при отрицательном результате анализа одного из вариантов в процессе поиска решения (скажем, очередного хода при игре в шахматы), что избавляет от необходимости поиска решения полным перебором вариантов и увеличивает эффективность реализации [21].

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

Нелинейность структуры программы является общей особенностью декларативного подхода и, строго говоря, является оригинальной характеристикой, а не объективным недостатком.

3.3. Объектно-ориентированные языки программирования

Объектно-ориентированные языки – это языки программирования, поддерживающие концепцию объектно-ориентированного программирования (ООП) [6, с.28].

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

Концепция объектно-ориентированного программирования складывается из трёх ключевых понятий: абстракция данных, наследование и полиформизм [10, с.9].

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

В повседневной жизни мы часто сталкиваемся с разбиением классов на подклассы. В программировании класс также может породить множество подклассов. Класс, порождающий другие классы, называется базовым. Порождённые им классы наследуют его свойства, но могут обладать и собственными. Такие классы называются производными. А сам процесс выделения производных классов из базового – наследованием [10, с.10].

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

Первым объектно-ориентированным языком программирования в истории является Симула. Он был разработан в конце 1960-х годов сотрудниками норвежского вычислительного центра (Осло) Кристеном Нюгордом и Оле-Йоханом Далем с целью моделирования сложных систем, что отразилось на его названии (simulation - моделирование). Наиболее известна версия Симула-67. Язык является расширением Алгола-60. Симула в значительной степени опередила свое время, программисты 1960-х годов оказались не готовы воспринять ее ценности, она не выдержала конкуренции прежде всего с Фортраном [22].

Smalltalk («смо́лток», в переводе - светская беседа) - объектно-ориентированный язык программирования с динамической типизацией, разработанный в лаборатории Xerox PARC Аланом Кэйем, Дэном Ингаллсом, Тедом Кэглером и другими в 1970-х годах. Язык был представлен как стандартная версия Smalltalk-80. Smalltalk представляет собой воплощение идей ООП в чистом виде. Решение принимается с помощью посылки сообщения ifTrue: логическому объекту, управление переходит к указанному фрагменту текста, если значение истинно. В языке всего три базовых конструкции: посылка сообщения объекту, присваивание объекта переменной, возвращение объекта из метода. Smalltalk оказал большое влияние на развитие многих современных языков программирования [22].

Наиболее современные и активно используемые в индустрии информационных технологий языки - С++, C#, Java - являются объектно-ориентированными. В мире ежегодно проводятся сотни специализированных конференций, посвященных объектно-ориентированному программированию (ООП) [13, с.47].

Средства ООП добавляются не только в императивные языки (так из Си получились С++ и Objective C), но и, например, в функциональные (Лисп - CLOS, Common Lisp Object System). Провозглашается, что объектно-ориентированный подход позволяет создавать более легко сопровождаемые и модифицируемые сложные программные системы [13, с.47].

Среди других примеров можно назвать Visual Basic, Eiffel, Oberon, Ruby.

Объектно-ориентированные языки можно разделить на три группы (рис. 7).

  1. Чистые языки, в наиболее классическом виде поддерживающие объектно-ориентированную методологию.
  2. Гибридные языки, которые появились в результате внедрения объектно-ориентированных конструкций в популярный императивный язык программирования.
  3. Урезанные языки, которые появились в результате удаления из гибридных языков наиболее опасных и ненужных с объектно-ориентированной точки зрения конструкций [20].

Рисунок 7 – Объектно-ориентированные языки программирования [20]

Развитием событийно управляемой концепции объектно-ориентированного подхода стало появление в 90-х г.г. целого класса языков программирования, которые получили название языков сценариев или скриптов. Под сценарием подразумевается некий набор действий, исполняемых операционной системой, браузером или иным подобным программным компонентом. При этом скрипт (программа на языке сценариев) интерпретируется соответствующим компонентом. Типичный пример – язык командной строки, с помощью которого можно задать операции над файлами в указанной папке [21].

К этой группе относят, например, такие популярные языки, как VBScript, PowerScript, LotusScript, JavaScript, Perl, PHP, BASH, и другие.

Как уже говорилось, в настоящее время объектно-ориентированное программирование является магистральным путем развития в индустрии информационных технологий. Апологеты ООП говорят прежде всего о следующих достоинствах объектно-ориентированных систем:

  • возможности повторного использования;
  • упрощение создания сложных систем за счет использования абстракции;
  • удобство сопровождения и модификации объектно-ориентированных программ [13, с.53].

У ООП есть и ряд довольно авторитетных критиков, которые, в частности, обращают внимание на следующие обстоятельства:

  • внедрение ООП требует дополнительных затрат на обучение программистов и накладных расходов при создании программ— от 12 до 75 % времени;
  • наследование в моделировании не существует;
  • инкапсуляция и повторное использование возможны и без ООП при правильной модульной организации программной системы [13, с.53].

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

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

ЗАКЛЮЧЕНИЕ

Итак, язык программирования - формализованный язык, предназначенный для описания программ и алгоритмов решения задач на ЭВМ. Языки программирования являются искусственными, в них синтаксис и семантика строго определены. Уровень языка программирования обычно определяется в зависимости от степени детализации предписаний - чем меньше детализация, тем выше уровень языка. По этому критерию можно выделить следующие уровни языков программирования: машинные; машинно-ориентированные (языки ассемблера); машинно-независимые (языки высокого уровня).

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

Язык высокого уровня - язык программирования, средства которого обеспечивают описание задачи в наглядном, легко воспринимаемом виде, удобном для программиста. Он не зависит от внутренних машинных кодов ЭВМ любого типа, поэтому программы, написанные на языках высокого уровня, требуют перевода в машинные коды программами транслятора либо интерпретатора. К языкам высокого уровня относят Фортран, ПЛ/1 , Бейсик, Паскаль, Си, Ада и др.

Мы выделили процедурные (императивные) и непроцедурные языки программирования высокого уровня.

Процедурное программирование - это запись алгоритма средствами языка программирования. При этом ожидаемые свойства результата обычно не указываются. Основные понятия языков этих групп (Basic, Pascal, С и др.) - оператор и данные. При процедурном подходе операторы объединяются в процедуры. Данные языки предназначены для однозначного описания алгоритмов в виде некоторой последовательности операторов языка.

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

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

В языках функционального программирования (Lisp, ML, Miranda, Erlang и Haskell и др.) вычисления в основном производятся путём применения функций к заданному набору данных. Таким образом, любая программа, написанная на таком языке, может интерпретироваться как функция с одним или несколькими аргументами. Такой подход дает возможность прозрачного моделирования текста программ математическими средствами.

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

В настоящее время особое место в программировании занимает объектно-ориентированный подход. Вместо проблемы разбиения задачи на функции, в объектно-ориентированном программировании задача представляется в виде совокупности объектов. Набор действий, или операций, применимых к объекту, определяется его классом, или типом. Кроме этого, объект каждого класса определяется характерным для него набором свойств, или атрибутов. Концепция объектно-ориентированного программирования складывается из трёх ключевых понятий: абстракция данных, наследование и полиформизм.

Программа на объектно-ориентированном языке (Object Pascal, C++, Java, C# и др.), решая некоторую задачу, по сути, описывает часть мира, относящуюся к этой задаче. Описание действительности в форме системы взаимодействующих объектов естественнее, чем в форме взаимодействующих процедур.

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

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

  1. Белов М. П. Основы алгоритмизации в информационных системах: Учеб. пособие. - СПб.: СЗТУ, 2003. - 85 с.
  2. Гедранович В.В. Основы компьютерных информационных технологий: учеб.-метод. комплекс / В.В. Гедранович, Б.А. Гедранович, И.Н. Тонкович. – 2-е изд., стереотип. – Минск: Изд-во МИУ, 2011. – 344 с.
  3. Зыков С. В. Программирование. Функциональный подход: учебник и практикум для академического бакалавриата / С. В. Зыков. — М.: Издательство Юрайт, 2016. - 164 с.
  4. Информационные системы в экономике: учеб. пособие /. Л.А Яковлева, Г.С Ветрова; КемТИПП – Кемерово, 2006. – 96 с.
  5. Исаева Г.Н., Пахомов Д.А. Возможности современных языков программирования высокого уровня // Современные информационные технологии / под науч. ред. док.техн. наук, проф. В.М. Артюшенко. – М.: Издательство «Научный консультант», 2015. – С. 167-175.
  6. Кадырова Г. Р. Основы алгоритмизации и программирования: учебное пособие / Г. Р. Кадырова. – Ульяновск: УлГТУ, 2014. – 95 с.
  7. Казакова А. Е. Методологические основания развития языков программирования: диссертация ... кандидата философских наук. - Москва, 2008. - 146 с. 
  8. Макарова Н. В., Волков В. Б. Информатика: Учебник для вузов. — СПб.: Питер, 2015. - 576 с.
  9. Могилев А. В. Методы программирования. Компьютерные вычисления / А. В. Могилев, Л. В. Листрова. - СПб.: БХВ-Петербург, 2008. - 320 с.
  10. Молдованова О.В. Языки программирования и методы трансляции: Учебное пособие. – Новосибирск/СибГУТИ, 2012. – 134с.
  11. Пахомов Д.А., Клешнев И.Б., Исаева Г.Н. Языки программирования высокого уровня, обеспечивающие создание безопасных приложений пользователя // Ресурсам области - эффективное использование / Сборник материалов XV Ежегодной научной конференции студентов Финансово-технологической академии. Часть 1 – Королев М.О.: Финансово технологическая академия, 2015. – С. 125-131.
  12. Себеста Р.У. Основные концепции языков программирования [Пер. с англ. Д. А. Клюшина, А. В. Назаренко]. - 5 изд. - М.: Вильямс, 2001. - 668 с.
  13. Тюгашев А.А. Основы программирования. Часть I. – СПб: Университет ИТМО, 2016. – 160 с.
  14. Алексеев Е.Г., Богатырев С.Д. Информатика. Мультимедийный электронный учебник. URL: http://inf.e-alekseev.ru/text/toc.html. (Дата обращения: 08.02.2018).
  15. Альсова О. К. и др. Информатика: учебник. – Новосибирск: Новосибирский государственный технический университет, 2012. URL: http://optic.cs.nstu.ru/files/CC/C/Lit/Informatica/info/about.html. (Дата обращения: 08.02.2018).
  16. Баржаксынова А.И. Алгоритмизация и программирование: учебник. URL: http://lib.kstu.kz:8300/tb/books/Algoritmizatciya_i_programmirovanie/my/ main.htm. (Дата обращения: 08.02.2018).
  17. Бекман И. Н. Компьютерные науки. Курс лекций. URL: http://profbeckman.narod.ru/. (Дата обращения: 08.02.2018).
  18. Непейвода Н. Н., Скопин И. Н. Основания программирования. URL: http://people.toiit.sgu.ru/Sinelnikov/PT/Nepeivoda/nepeivoda_prog.pdf. (Дата обращения: 08.02.2018).
  19. Основы программирования. URL: http://www.kufas.ru/programming0.htm. (Дата обращения: 08.02.2018).
  20. Системный подход в технологии программирования. URL: https://bourabai.ru/alg/system.htm. (Дата обращения: 08.02.2018).
  21. Современные языки программирования и .NET. Учебный курс. М.: Московского инженерно-физического института (государственного университета), 2003. URL: http://window.edu.ru/catalog/pdf2txt/686/41686/18844. (Дата обращения: 08.02.2018).
  22. Соколов В.В. Эволюция языков программирования. URL: http://www.ait.org.ua/p/pub_evolution.html. (Дата обращения: 08.02.2018).