logo
Лекции по информатике / Раздел07(Эволюция и классифкация языков программирования)

Классификация и обзор языков программирования

Деление языков программирования на классы можно представить на схеме таким образом:

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

Различают такие языки процедурного программирования:

Язык Фортран В 1954 году в недрах корпорации IBM группой разработчиков во главе с Джоном Бэкусом (John Backus) был создан язык программирования Fortran.

Значение этого события трудно переоценить. Этопервый язык программирования высокого уровня. Впервые программист мог по-настоящему абстрагироваться от особенностей машинной архитектуры. Ключевой идеей, отличающей новый язык от ассемблера, была концепция подпрограмм. Напомним, что это современные компьютеры поддерживают подпрограммы на аппаратном уровне, предоставляя соответствующие команды и структуры данных (стек) прямо на уровне ассемблера, в 1954 же году это было совершенно не так. Поэтому компиляция Fortran’а была процессом отнюдь не тривиальным. Кроме того, синтаксическая структура языка была достаточно сложна для машинной обработки в первую очередь из-за того, что пробелы как синтаксические единицы вообще не использовались. Это порождало массу возможностей для скрытых ошибок, таких, например:

В Фортране следующая конструкция описывает «цикл for до метки 10 при изменении индекса от 1 до 100»:

DO 10 I=1,100

Если же здесь заменить запятую на точку, то получится оператор присваивания:

DO10I = 1.100

Говорят, что такая ошибка заставила ракету взорваться во время старта!

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

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

Кобол – создан в конце 60-х годов XX-го века для решения задач обработки больших объемов данных, хранящихся на различных носителях данных. Он задумывался как язык для создания коммерческих приложений, и он стал таковым. На Коболе написаны тысячи прикладных коммерческих систем. Отличительной особенностью языка является возможность эффективной работы с большими массивами данных, что характерно именно коммерческих приложений. Популярность Кобола столь высока, что даже сейчас, при всех его недостатках (по структуре и замыслу Кобол во многом напоминает Фортран) появляются новые его диалекты и реализации. Так недавно появилась реализация Кобола, совместимая с Microsoft .NET, что потребовало, вероятно, внесения в язык некоторых черт объектно-ориентированного языка.

Алгол – В 1960 году командой во главе с Петером Науром (Peter Naur) был создан язык программирования Algol. Это многоцелевой расширенный язык программирования. В нем впервые введены понятия «блочная структура программы» и «динамическое распределение памяти»; Этот язык дал начало целому семейству Алгол-подобных языков (важнейший представитель  Pascal).

В 1964 году в Дартмурском колледже (Dartmouth College) был создан язык программирования BASIC (Beginners’ All-Purpose Symbolic Instruction Code  многоцелевой язык символических инструкций для начинающих). Язык задумывался в первую очередь как средство обучения и как первый изучаемый язык программирования. Он предполагался легко интерпретируемым и компилируемым. Надо сказать, что BASIC действительно стал языком, на котором учатся программировать (по крайней мере, так было еще несколько лет назад; сейчас эта роль отходит к Pascal). Было создано несколько мощных реализаций BASIC, поддерживающих самые современные концепции программирования (ярчайший пример  Microsoft Visual Basic).

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

В 1963-1966гг корпорацией IBM был создан многоцелевой универсальный язык PL-1, который был призван заменить Cobol и Fortran в большинстве приложений. Этот язык хорошо приспособлен для исследования и планирования вычислительных процессов, моделирования, решения логических задач, разработки систем математического обеспечения. Язык обладал исключительным богатством синтаксических конструкций. В нем впервые появилась обработка исключительных ситуаций и поддержка параллелизма. Надо заметить, что синтаксическая структура языка была крайне сложной. Пробелы уже использовались как синтаксические разделители, но ключевые слова не были зарезервированы. В частности, следующая строка — это вполне нормальный оператор на PL/1:

IF ELSE=THEN THEN THEN; ELSE ELSE

В силу таких особенностей разработка компилятора для PL/1 была исключительно сложным делом. Язык так и не стал популярен вне мира IBM.

Язык Паскаль (PASCAL) (1968-1971гг)  язык процедурного программирования наиболее популярный для ПК, который и в настоящее время успешно применяется.

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

В основу языка Pascal положен подход от общей задачи к частным (более простым и меньшим по объему).

К основным принципам, которыми обладает Паскаль, можно отнести:

Отрицательной чертой языка было отсутствие в нем средств для разбиения программы на модули. Вирт осознавал это и разработал язык Modula-2 (1978), в котором идея модуля стала одной из ключевых концепций языка. В 1988 году появилась Modula-3, в которую были добавлены объектно-ориентированные черты. Логическим продолжением Pascal и Modula являются язык Oberon и Oberon-2. Они характеризуются движением в сторону объектно- и компонентно- ориентированности.

В 1983 году под эгидой Министерства Обороны США был создан язык Ada. Его отличает модульность конструкций. Язык замечателен тем, что очень много ошибок может быть выявлено на этапе компиляции. Кроме того, поддерживаются многие аспекты программирования, которые часто отдаются на откуп операционной системе (параллелизм, обработка исключений). В 1995 году был принят стандарт языка Ada 95, который развивает предыдущую версию, добавляя в нее объекно-ориентированность и исправляя некоторые неточности. Оба этих языка не получили широкого распространения вне военных и прочих крупномасштабных проектов (авиация, железнодорожные перевозки). Основной причиной является сложность освоения языка и достаточно громоздкий синтаксис (значительно более громоздкий, чем Pascal).

Язык СИ (начало 70-х годов) также относится к языкам процедурного программирования. Первоначальный его вариант планировался как язык для реализации операционной системы Unix вместо языка Ассемблера. Одной из особенностей языка СИ является то, что различия между выражениями и операторами сглаживаются, что приближает его к функциональным языкам программирования. Кроме того, в языке СИ отсутствует понятие процедуры, а использование подпрограмм основано на понятии функции, которая может сочетать в себе возможности процедуры. С одной стороны, по набору управляющих конструкций и структур данных его можно отнести к языкам высокого уровня, а с другой – он имеет набор средств прямого обращения к функциональным узлам компьютера, а это означает, что его можно использовать как операционный язык.

Объектно-ориентированное программирование (ООП)

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

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

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

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

Следующими важнейшими принципами ООП являются наследование и полиморфизм.

Наследование предусматривает создание новых классов на базе существующих и позволяет классу потомку иметь (наследовать) все свойства класса – родителя.

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

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

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

Simula

Первым объектно-ориентрованным языком был язык Simula (1967). Этот язык был предназначен для моделирования различных объектов и процессов, и объектно-ориентированные черты появились в нем именно для описания свойств модельных объектов.

Smalltalk

Популярность объектно-ориентированному программированию принес язык Smalltalk, созданный в 1972 году. Язык предназначался для проектирования сложных графических интерфейсов и был первым по-настоящему объектно-ориентированным языком. В нем классы и объекты — это единственные конструкции программирования. Большим недостатком Smalltalk являются большие требования к памяти и низкая производительность полученных программ. Это связано с не очень удачной реализацией объектно-ориентированных особенностей. Популярность языков C++ и Ada 95 связана именно с тем, что объектно- ориентированность реализована без существенного снижения производительности.

Eiffel

Существует язык с очень хорошей реализацией ООП, не являющийся надстройкой ни над каким другим языком. Это язык Eiffel (1986). Являясь чистым языком объектно-ориентированного программирования, он, кроме того, повышает надежность программы путем использования «контрольных утверждений».

Наиболее современными языками программирования являются С++ и Java. С середины 90-х годов многие объектно-ориентированные языки реализуются как системы визуального проектирования, в которых интерфейсная часть программного продукта создается в диалоговом режиме, практически без написания программных операторов. К объектно-ориентированным системам визуального проектирования относятся Visual Basic, Delphi, C++ Builder, Visual C++.

Язык VBA (Visual Basic for Application) – язык приложений Microsoft Office (Excel, Word, Power Point и др). VBA соблюдает основной синтаксис языка и правила программирования языков Basic – диалектов, позволяет создавать макросы для автоматизации выполнения некоторых операций и графический интерфейс пользователя, интеграцию между различными программными продуктами.

Декларативные языки программирования

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

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

Первым языком стал язык Лисп (LISP, LIST Processing обработка списков) создан в 1959г. Этот язык позволяет обрабатывать большие объемы текстовой информации.

Язык Лисп  один из наиболее распространенных базовых языков искусственного интеллекта.

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

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

Популярность Лиспа объясняется следующими причинами:

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

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

3) Идеология Лиспа крайне проста: данные и программы представляются в нем в одной и той же форме. Благодаря такой унификации представления данные могут интерпретироваться как программа, а любая программа может быть использована как данные любой другой программой.

4) Язык Лисп является языком функционального программирования. Применение функциональных языков открывает широкие перспективы, позволяя пользователю описывать скорее природу своих задач, чем способ их решения [7,8].

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

Логическое программирование это программирование в терминах логики. Основывается на формальной логике и Булевой алгебре (в некоторых языках применяются средства нечёткой логики, что позволяет создавать системы искусственного интеллекта). Программа, записанная на логическом языке программирования, не содержит в себе конкретных алгоритмов (действий и команд типа сделать то, затем это). Задаётся описание условий задачи и логических отношений, по которым система программирования сама рассчитывает возможные следствия и взаимосвязи введённых данных и формул.

В 1973 году был создан язык искусственного интеллекта Пролог (PROLOG) (Programming in Logic). Программа на языке Пролог строится из последовательности фактов и правил, затем формулируется утверждение, которое Пролог пытается доказать с помощью правил. Язык сам ищет решение с помощью методов поиска и сопоставления, которые в нем заложены.

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

Языки программирования баз данных.

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

Для обработки больших массивов информации и выборки записей по определенным признакам был создан структурированный язык запросов SQL (Structured Query Language) 1986 год.. Язык SQL – это стандартный язык работы с реляционными базами данных.

Сегодня в мире ведущие производители СУБД: Microsoft (SQL Server), IBM (DB2), Oracle, Software AG (Adabas), Informix и Sybase. Практически в каждой СУБД имеется свой встроенный язык работы с БД. Так, например, в Oracle имеется встроенный язык PL/SQL, в Informix – INFORMIX 4GL, в Adabas – Natural и т.д.

Языки программирования для компьютерных сетей

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

Язык HTML (Hyper Text Markup Language) – универсальный язык разметки гипертекста, используемый для подготовки Web документов для Internet. Язык позволяет форматировать текст, добавлять графические образы, работать с таблицами и организовывать связь одного документа с другим с помощью механизма гиперссылок.

Язык Perl (80 г) содержит многочисленные функции работы со строками, массивами, всевозможные средства преобразования данных.

Язык PHP (1995-1997гг) обладает средствами доступа к БД и используется создателями динамических сайтов во всем мире.

Язык Tcl/Tk (конец 80-х годов) состоит из мощных команд, предназначенных для работы с абстрактными нетипизированными объектами и позволяет создавать программы с графическим интерфейсом.

Язык VRML (1994г) создан для организации виртуальных трехмерных интерфейсов в Интернете.

Язык XML. С 1996г идет работа над созданием универсального языка структуры документов. Является заменой языка HTML.

Языки искусственного интеллекта

Интерес к языкам искусственного интеллекта возник в 50-е гг., когда компанией Rand Corporation был разработан язык IPL (Information Processing Language). Версия IPL-V стала довольно широко известна, но ее использование ограничивалось тем, что IPL-V не был языком высокого уровня.

Огромным шагом вперед стала разработка Джоном Мак-Карти, сотрудником Массачусетсского технологического института (MIT), языка LISP (LISt Processing) для компьютеров IBM 704. Версия LISP 1.5 стала стандартом для его реализации на многие годы. Развитие LISP продолжается до настоящего времени. LISP разрабатывался как функциональный язык обработки списков. Естественной областью приложения LISP явилась разработка стратегии ведения игры, поскольку обычная программа, написанная на языке LISP, могла создавать дерево возможных направлений движения (как связанный список) и, продвигаясь по этому дереву, искать оптимальную стратегию.

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

В этой области первой разработкой был язык COMIT, созданный Ингве, сотрудником MIT. Каждый оператор программы, написанной на этом языке, был очень похож на контекстно-независимое правило и представлял собой набор замен, которые можно было осуществить, если в исходных данных обнаруживалась конкретная цепочка символов. Поскольку Ингве запатентовал свой код, группа разработчиков из AT&T Bell Telephone Laboratories решила создать свой собственный язык — так появился SNOBOL.

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

Одновременно с развитием универсальных языков высокого уровня стали развиваться проблемно-ориентированные языки программирования, которые решали экономические задачи (COBOL), задачи реального времени (Modula-2, Ada), символьной обработки ( Snobol), моделирования (GPSS, Simula, SmallTalk), численно-аналитические задачи (Analitic) и другие. Эти специализированные языки позволяли более адекватно описывать объекты и явления реального мира, приближая язык программирования к языку специалиста в проблемной области.

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

К непроцедурным языкам относят и языки запросов систем управления базами данных (QBE, SQL).

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

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

1. По степени ориентации на специфические возможности ЭВМ языки программирования делятся на:       · машинно-зависимые;       · машинно-независимые.

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

2. По степени детализации алгоритма получения результата языки программирования делятся на:       · языки низкого уровня;       · языки высокого уровня;       · языки сверхвысокого уровня.    3. По степени ориентации на решение определенного класса задач:       · проблемно-ориентированные;       · универсальные.    4. По возможности дополнения новыми типами данных и операциями:       · расширяемые;       · нерасширяемые.    5. По возможности управления реальными объектами и процессами:       · языки систем реального времени;       · языки систем условного времени.    6. По способу получения результата:       · процедурные;       · непроцедурные.    7. По типу решаемых задач:       · языки системного программирования;       · языки прикладного программирования.    8. Непроцедурные языки по типу встроенной процедуры поиска решений делятся на:       · реляционные;       · функциональные;       · логические.

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

Тенденции развития языков программирования

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

Языки системного программирования, на которых создаются операционные системы, трансляторы и другие системные программы, развиваются в направлении повышения их уровня и независимости от ЭВМ. На сегодняшний день почти 90% системного программного обеспечения создается не на языке ассемблера, а на языке C. Например, операционная система Unix практически полностью написана на C. Язык C позволяет получать программы, сравнимые по своей эффективности с программами, написанными на языке ассемблера. Правда, объем программ получается больше, но зато эффективность их создания гораздо выше.

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

Другим направлением является повышение уровня самого машинного языка. Например, известны Lisp-машины, в которых машинным языком является язык Lisp (реализован аппаратно). Другим примером являются ЭВМ 5-го поколения с машинным языком искусственного интеллекта Prolog.

Языки высокого уровня развиваются в направлении поддержки технологий программирования, обеспечения низкоуровневых операций (уровня ассемблера), обеспечения новых информационных технологий (НИТ) и независимости от среды реализации. Следует сказать, что по своим возможностям языки высокого уровня постепенно сближаются и программисту на C все труднее становится спорить о преимуществах языка C с программистом, работающим на языке Basic.

Тотальный бум переживает технология объектно-ориентированного программирования (ООП): практически все современные ЯВУ поддерживают ООП. Да и все современные программные системы построены на принципах ООП, и сегодня каждый программирующий студент знает, что такое инкапсуляция, наследование и полиморфизм. Для обозначения факта поддержки ООП языки получают приставку Object (например, ObjectPascal) или другие (например, C++).

Windows, сети ЭВМ, серверы, базы данных и Internet, как основа НИТ, оказывают сильнейшее влияние на современные языки программирования. Разработчики языка программирования просто обязаны включать в языки средства поддержки НИТ, чтобы привлечь программистов на свою сторону. Для поддержки Windows создаются системы визуального программирования с приставкой Visual, например Visual C++, Visual Basic и др. Для работы с базами данных , сетями и Internet в язык программирования включаются специальные внутренние или внешние средства.

Стремление к созданию программ, независимых от типа ЭВМ и операционной системы, привело к созданию языка Java. Основная задача Java  обеспечить выполнение программ, распространяемых через Web-страницы Internet, на любой рабочей станции. Кроме того, Java поддерживает все средства НИТ.

Популярность языков искусственного интеллекта за последние 10 лет, к сожалению, заметно упала. Это связано прежде всего с психологическими проблемами, которые испытывают программисты при использовании этих языков. Например, в мощнейшем языке Lisp программа имеет очень сложную для понимания списочную структуру и небольшой по объему проект очень быстро выходит из под контроля. В языке Prolog программист должен точно знать логику работы встроенной машины логического вывода, а работа программы зависит от структуры и содержимого базы знаний (БЗ). Если с проектированием программы и структуры БЗ программист справляется, то для заполнения БЗ он должен быть экспертом в предметной области либо тесно контактировать с экспертом и извлекать из него знания, а то и другое является сложной задачей.

Поэтому необходимы дополнительные обеспечивающие средства для возврата популярности этих языков.

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

21