Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Proc(i, 45.0); // He нужна операция получения адреса




СОДЕРЖАНИЕ

Глава 1 Основные понятия и определения курса. 4

1.1.  Место дисциплины в учебном процессе. 4

1.2.  Основные понятия и определения курса. 6

1.3.  История развития языков программирования. 10

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

1.5.  Основные понятия и определения алгоритмического языка. 28

1.6.  Эволюция языков программирования. 31

Глава 2 Парадигма процедурного программирования. 35

2.1   Основные характеристики процедурных языков программирования. 35

Фортран. 35

Cobol 36

PL/1. 36

BASIC.. 36

Algol и его потомки. 37

Pascal-подобные языки. 37

C-подобные языки. 38

2.2   Эволюция процедурных языков программирования. 39

2.3   Развитие концепции структуризации данных. 41

Понятие типа данных. 41

Простой тип и составной тип. 43

Система типов данных. 44

Классификация систем типизации. 45

Статическая и динамическая типизация. 46

Типизация и связывание. 49

Система типов платформы .NET. 51

2.4   Абстрагирование типов. 54

2.5   Инкапсуляция. 56

Модульность. 56

Модульность сегодня. 57

2.6   Подпрограммы: процедуры и функции. 61

Передача параметров подпрограмме. 63

Глава 3 Парадигма объектного программирования. 69

3.1   Инкапсуляция. 69

3.2   Спецификация классов на основе абстрагирования. 70

3.3   Иерархия классов и наследование. 74

3.4   Иерархия классов и абстракция. 76

3.5   Отношения между классами. 77

3.5.1    Ассоциация. 78

3.5.2    Наследование. 79

3.5.3    Механизм наследования. 81

3.6   Агрегация. 84

3.7   Полиморфизм.. 85

3.8   Описание поведения класса (управление событиями) 89

3.9   Вместо заключения. 92

Глава 4 Парадигма функционального программирования. 93

4.1   Основы функционального программирования. 93

4.2   Ламбда-исчисление как формальная система. 94

Глава 5 Введение в теорию трансляции ЯП.. 99

5.1   Задачи интерпретатора. 100

5.2   Задачи компиляторов. 101

Объектная программа. 102


ГЛАВА 1 ОСНОВНЫЕ ПОНЯТИЯ И ОПРЕДЕЛЕНИЯ КУРСА

1.1. Место дисциплины в учебном процессе

Программирование вообще и дисциплина «Языки программирования» в частности стоят в центре учебного плана любой специальности, связанной с информационными автоматизированными системами и информационными технологиями. Это касается и специальности 010400 – «Информационные технологии», по которой вы обучаетесь в нашем университете. В соответствии с Государственным образовательным стандартом (ГОС) данной специальности ядром (центральной частью) является блок «Программирование», в который входят такие дисциплины, как «Языки программирования» и «Алгоритмы и анализ сложности».


 

 


1.2. Основные понятия и определения курса

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

 

 

 


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

1) восприятие информации (рецепция, получение и сохранение) от источника информации;

2) интерпретация информации (преобразование, моделирование) в соответствии с потребностями и/или возможностями приёмника и построение адекватной информационной модели источника информации;

3) коммуникация информации (транспортировка) - пространственно-временная передача информации от источника к приёмнику.

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

1. Философский уровень. «Информация – это информация, а не энергия и не материя» (Норберт Винер – основоположник кибернетики поставил информацию в один ряд с другими наиболее общими философскими категориями).

2. Бытовой уровень. «Информация – это: 1) сведения об окружающем мире и протекающих в нем процессах; 2) сообщения, осведомляющие о положении дел, о состоянии чего-либо» (С.И. Ожегов – составитель словаря русского языка).

3. Правовой уровень. «Информация - сведения о лицах, предметах, фактах, событиях, явлениях и процессах независимо от формы их представления» (закон «Об информации, информационных технологиях и защите информации»).

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

Данные (data) – это представление фактов и идей в формализованном виде, пригодном для передачи и переработке в некоем информационном процессе¨, исходя из этого информация - это смысл, который придается данным при их представлении.

Данные представляются и хранятся на так называемых носителях данных. Совокупность носителей данных, используемых при какой-либо обработке данных, называется информационной средой (data medium). Набор данных, содержащихся в какой-либо момент в информационной среде, называется состоянием этой информационной среды. Поэтому описать процесс - это значит определить последовательность состояний заданной информационной среды. Формализованное описание процесса называется программой, с ее помощью информационный процесс на компьютере порождается автоматически. С другой стороны, программа должна быть понятной и человеку, так как и при разработке программ, и при их использовании часто приходится выяснять, какой именно процесс она порождает. Поэтому программа составляется на удобном для человека формализованном языке программирования, с которого она автоматически переводится на язык соответствующего компьютера с помощью транслятора.

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

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

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

Примечание: Принято считать, что сам термин алгоритм происходит от имени персидского математика Абу-Ждафара Мохаммеда Ибн-Мусы Аль-Хорезми, который в 825 г. описал правила выполнения арифметических действий в десятичной системе счисления. Понятие алгоритма стало предметом соответствующей теории - теории алгоритмов, которая занимается изучением общих свойств алгоритмов, какой-то период времени языки программирования назывались алгоритмическими.

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

Программа (program) - это набор операторов, который может быть представлен как единое целое в некоторой вычислительной системе и который используется для управления поведением этой системы.

Программирование (programming) - это:

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

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

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

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

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

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

Создатели языков по-разному толкуют понятие «язык программирования». К наиболее распространенным утверждениям, признаваемым большинством разработчиков, относятся следующие:

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

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

Исполнение: ЯП может использовать специальные конструкции для определения и манипулирования структурами данных и управления процессом вычислений.

Изучением знаковых систем занимается наука семиотика. Знак – это соглашение (явное или неявное) о приписывании чему-либо какого-то определенного смысла. Существует так называемый семантический треугольник, представленный на рисунке 1.3.

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

 

 

 


Синтаксис (от греч. Syntaxis - порядок) – раздел грамматики и семиотики, отвечающий за построение языковых конструкций.

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


1.3. История развития языков программирования

Аппаратура – вот тот «кит», который определяет все новое в программировании. К конечном счете, все новые идеи в программировании идут от новых технологий в разработке аппаратного обеспечения ЭВМ (см. лекции по дисциплине «Архитектура ЭВМ»). Как показала история, развитие вычислительной техники происходит скачкообразно, это приводит к пересмотру общих концепций и возникновению новых парадигм программирования и, как следствие, новых ЯП. Парадигма – это новая модель конструирования программы и взаимодействия ее с данными.

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

 

 

 


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

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

Для ЭВМ второго поколения (1956-1960 г.г.) были созданы первые языки программирования - ассемблеры, а затем и ЯП высокого уровня – Fortran, Algol, PL/1, Pascal, которые оказались подходящими и для программирования ЭВМ третьего поколения. Они упростили программирование вычислений, снизив уровень детализации операций, что позволило повысить уровень сложности программ.

Примечание 1: Не очень заметный, казалось бы, шаг - переход к символическому кодированию машинных команд — имел на самом деле огромное значение. Программисту не надо было больше вникать в хитроумные способы кодирования команд на аппаратном уровне. Более того, зачастую одинаковые по сути команды кодировались совершенно различным образом в зависимости от своих параметров (широко известный пример из мира современных компьютеров - это кодирование инструкции mov в процессорах Intel: существует несколько совершенно по-разному кодируемых вариантов команды; выбор того или иного варианта зависит от операндов, хотя суть выполняемой операции неизменна: поместить содержимое (или значение) второго операнда в первый). Появилась также возможность использования макросов и меток, что также упрощало создание, модификацию и отладку программ. Появилось даже некое подобие переносимости - существовала возможность разработки целого семейства машин со сходной системой команд и некоего общего ассемблера для них, при этом не было нужды обеспечивать двоичную совместимость.

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

Появление прерываний в ЭВМ третьего поколения (1960-1970 г.г.) (появление интегральных микросхем, транзисторов, диодов) привело к мультипрограммированию, а появление операционных систем (ОС) дало качественно новые возможности для управления вычислительным процессом. В ЭВМ третьего поколения произошло усложнение архитектуры за счет разделения процессов ввода-вывода информации и ее обработки (децентрализация); арифметико-логическое устройство (АЛУ) и устройство управления (УУ) были объединены в единое целое – процессор, все это позволило существенно повысить быстродействие ЭВМ.

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

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

Первоначально программа состояла из основной программы, области глобальных данных и набора подпрограмм, выполняющих обработку либо всех данных, либо только ее части (рисунок 1.5-А). Такая архитектура повышала вероятность искажения части глобальных данных какой-либо подпрограммой, поэтому для повышения надежности программ была предложена новая идея: использовать часть данных как локальные внутри подпрограмм (рисунок 1.5-Б).

 

 

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

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

Появились языки программирования (Clu, Pascal, Modula-2), отличительной особенностью которых явилось наличие развитых средств абстрагирования типов для структурирования данных, появление пользовательских типов позволило уменьшить количество ошибок при работе с глобальными данными. Объединение нескольких подпрограмм, использующих одни и те же данные, в отдельно компилируемые модули, связи между которыми устанавливались через специальный интерфейс, а доступ к реализации регулировался механизмами импорта-экспорта путем соответствующих деклараций (рисунок 1.6) позволило существенно повысить надежность программ.


 

 


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

Стоимость программного обеспечения стала расти и в настоящее время намного опережает стоимость аппаратных средств (рисунок 1.7).

 

 

 


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

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

ЭВМ пятого поколения (1990-1999 г.г.) были рассчитаны на «интеллектуальные пакеты программ», для которых традиционное программирование не подходит. Создание многопроцессорных систем привело к появлению параллелизма вычислений, появление мощных ПЭВМ и развитие телекоммуникационных технологий – к появлению сети Интернет и т.д. Появление сети Интернет дало возможность подключить к ней огромное количество пользователей, это поставило ряд проблем (как технологического, так и юридического и этического характера) регулирования доступа к информации.

В связи с этим появилась необходимость:

Ø в разработке пользовательских интерфейсов, не требующих специальной установки (обозреватели);

Ø в отделении логики приложений от пользовательского интерфейса;

Ø создания многоуровневых приложений и переноса их на мощные Интернет-серверы;

Ø доступа к функциям приложения с различных клиентских платформ и возможность создания интерактивных приложений, использующих функции WEB-серверов;

Ø создания ПС, работающих на разных платформах (с некоторыми ограничениями в совместимости и надежности).

Появление новых ЯП (языков разметки HTML, Active X, Java, Ruby), ориентированных на разработку WEB-приложений, дало возможность публиковать огромный объем информации, асинхронно использовать распределенные ресурсы и т.п.

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


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

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

Представим классификацию ЯП в виде таблицы, указывая вначале признак классификации, а затем класс языка (таблица 1.1).

1 признак. Эффективность труда разработчиков повышается за счет абстрагирования от конкретных деталей аппаратного обеспечения.

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

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

1.3 Шейдерные языки – это языки, занимающие промежуточное положение между языками ассемблера и ЯПВУ, в язык ассемблера добавлены команды, позволяющие работать с векторами и матрицами, и т.д.


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

№ п/п Признак классификации № п/п Класс ЯП Пример ЯП

1

Степень абстрагирования от особенностей машинной архитектуры

1.1 ЯП низкого уровня Ассемблеры
1.2 ЯП высокого уровня Все остальные ЯП
1.3. Шейдерные ЯП  

2

Принцип управления вычислительным процессом

2.1

Императивный

2.1.1 Операторный Assembler
2.1.2 Процедурный (процедурно-ориентированный) Fortran, Pascal, Ada, Cobol, Basic, APLàC,
2.2

Декларативный

2.2.1 Логический Prolog, KLO
2.2.2 Функциональный Lisp, APL, Logo, Haskell, ML

3

Модель вычислений (парадигма программирования)

3.1 Процедурный (процедурно-ориентированный) Fortran, Pascal, C, Ada, Cobol, Basic
3.2 Функциональный См. 2.2.2
3.3 Логический Prolog, KLO, Mercury
3.4 Объектный Simula, SmallTalk
3.4.1 Объектно-ориентированный Object Pascal, С#, C++, Java, Visual Basic, Oberon
3.5 Стековый Forth, Factor, Postscript
3.6 Проблемно-ориентированный Perl

4

Модель управления

4.1 Объектный (объектно-ориентированный) C++, Java, Visual Basic
4.2 Скриптовый JavaScript, VBScript

5

Типы данных

5.1 Со статической типизацией  
5.1.1 С обязательной декларацией (сильно-типизированный) Pascal
5.1.2 С выводимыми типами SML, C#
5.1.3 С полиморфной типизацией SML, C#
5.2 С динамической типизацией С, С++

6

Способ исполнения программы

6.1 Компилируемые Pascal
6.2 Интерпретируемые LISP, Perl
6.3 Смешанные Python

7

Семантика

7.1 Языки с семантиками, ориентированными на компиляцию  
7.2 Языки с семантиками, ориентированными на интерпретацию  
7.2.1 С операционной семантикой  
7.2.2 С пропозиционной семантикой  
7.2.3 С денотационной семантикой  

8

Механизм вычислений

8.1 Языки последовательных вычислений  
8.2 Языки параллельных вычислений Оccam

 

9

Тип решаемых задача

9.1 Задачи вычислительного характера Algol, Fortran, Cobol, Ada, PL/1, Basic, Pascal
9.2 Задачи вычислительной математики и физики Occam, PFOR, Glypnir, Actus,параллельный Cobol, ОВС-Фортран
9.3 Задачи искусственного интеллекта Lisp, Prolog, Multilisp, Commonlisp, Рефал, Planner
9.4 Задачи параллельных вычислений Apl, ML, SML, Miranda, Occam, ОВС-Фортран
9.5 Разработки интерфейса, программных оболочек или систем Forth, С, C++, Ассемблер, Макроассемблер, Simula-67, Smalltalk, Java
9.6 Оформления документов, обработка больших текстовых файлов HTML, Perl
9.7 Разработки баз данных QBE, SQL

 


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

2.1 Императивный ЯП (от лат. Imperativus - повелительный). Императивная программа состоит из последовательности операторов и предложений, управляющих последовательностью их выполнения (операторы ввода/вывода, присваивания, передачи управления и т.п.). В основе такого программирования лежат взятие значения какой-либо переменной, совершение над ней действия и сохранение нового значения с помощью операторов присваивания, и так до тех пор, пока не будет получено желаемое окончательное значение. Императивные языки подразделяются на операторные и процедурные (процедурно-ориентированный).

2.1.1 Операторный ЯП - язык программирования высокого уровня,

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

2.2 В 60-х годах возникает новый подход к программированию, который до сих пор успешно конкурирует с императивным, а именно, декларативный подход. Суть подхода состоит в том, что программа представляет собой не набор команд, а описание действий, которые необходимо осуществить.

Декларативный ЯП - язык программирования высокого уровня, построенный:

Ø на описании данных; и

Ø на описании искомого результата.

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

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


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

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

Декларативные языки подразделяются на 2.2.1 функциональные и 2.2.2 логические языки.

3 признак.Любой язык программирования строится в соответствии с той или иной базовой моделью вычислений (парадигмой программирования). Несмотря на то, что большинство ЯП ориентировано на так называемую императивную модель вычислений, задаваемую фон-неймановской архитектурой ЭВМ, существуют и другие подходы. Прежде всего следует упомянуть языки со стековой вычислительной моделью (Forth, Factor, Postscript и др), а также функциональные (Лисп, Haskell, ML и др.) и логические языки программирования (Пролог).

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

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

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

Языки функционального программирования не лишены недостатков: часто к ним относят нелинейную структуру программы и относительно невысокую эффективность реализации. Однако первый недостаток достаточно субъективен, а второй успешно преодолен современными реализациями трансляторов языков, включая и компилятор для среды Microsoft .NET.

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

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

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

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

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

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

3.4 Термин «объект» появился практически независимо в различных областях, связанных с компьютерами, и почти одновременно в начале 70-х годов для обозначения того, что может иметь различные проявления, оставаясь целостным. Объектами назывались компоненты системы или фрагменты представляемых знаний.

Важным шагом на пути к совершенствованию языков программирования стало появление объектно-ориентированного подхода к программированию (ООП) и соответствующего класса языков.

В рамках данного подхода программа представляет собой описание объектов, их свойств (или атрибутов), совокупностей (или классов), отношений между ними, способов их взаимодействия и операций над объектами (или методов).

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

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

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

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

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

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

4 признак. Развитием событийно управляемой концепции объектно-ориентированного подхода стало появление в 90-х годах целого класса языков программирования, которые получили название языков сценариев (скриптов).

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

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

Существенным преимуществом языков сценариев является их совместимость с передовыми инструментальными средствами автоматизированного проектирования и быстрой реализации программного обеспечения, или так называемыми CASE- (Computer-Aided Software Engineering) и RAD- (Rapid Application Development) средствами.

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

5 признак. Во внутреннем представлении обычно данные в современных цифровых компьютерах сохраняются в бинарном (двоичном) виде. Данные, которые представляют информацию из реального мира (имена, измерения и др.) - высокоуровневые концепции.

Типизация структурирует предметную область по иерархическому принципу. Особая система, по которой данные организуются в программе, -это система типов ЯП; разработка и изучение систем типов известна под названием теория типов. Языки могут быть классифицированы как системы со статической типизацией(5.1) и языки с динамической типизацией(5.2). Статически-типизированные языки могут быть в дальнейшем подразделены на языки с обязательной декларацией (5.1.1), где каждая переменная и объявление функции имеет обязательное объявление типа, и языки с выводимыми типами  (5.1.2).

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

Тот факт, что каждый объект программы должен быть типизирован до начала ее выполнения, не означает необходимости явного приписывания типа в ходе проектирования и реализации программы. Многие современные языки программирования имеют встроенный механизм выводимости типов (type inference). Это означает, что тип некоторых выражений языка может быть выведен из контекста окружающих его выражений, типы которых уже известны, путем сопоставления (при этом учитываются объемлющие и внутренние функции, аппликация, присваивание и другие операции). Ярким примером языка с выводимостью типов является функциональный язык LISP, который с одинаковым успехом обрабатывает списки, построенные на любом типе данных.

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

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

6 признак. Программа на компилируемом языке при помощи специальной программы компилятора преобразуется (компилируется) в набор инструкций для данного типа процессора (машинный код) и далее записывается в исполняемый файл, который может быть запущен на выполнение как отдельная программа. Другими словами, компилятор переводит программу с языка высокого уровня на низкоуровневый язык, понятный процессору.

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

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

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

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

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

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

Некоторые языки, например, Java и C#, находятся между компилируемыми и интерпретируемыми. А именно, программа компилируется не в машинный язык, а в машинно-независимый код низкого уровня, байт-код. Далее байт-код выполняется виртуальной машиной. Для выполнения байт-кода обычно используется интерпретация, хотя отдельные его части для ускорения работы программы могут быть транслированы в машинный код непосредственно во время выполнения программы по технологии компиляции «на лету» (Just-in-time compilation, JIT). Для Java байт-код исполняется виртуальной машиной Java (Java Virtual Machine, JVM), для C# — Common Language Runtime.

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

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

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

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

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

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

Существует три основных вида семантик, ориентированных на интерпретацию.

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

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

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

Наиболее широко распространены разновидности следующих: операционного (денотационного или так называемого математического), и деривационного (или аксиоматического).

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


1.5. Основные понятия и определения алгоритмического языка

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

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

- алфавит допустимых символов и ключевых слов;

- синтаксические правила построения из алфавита допустимых конструкций языка;

- семантику, объясняющую смысл и назначений конструкций языка.

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

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

Описание языка – это иерархическое описание четырех элементов:

Ø Символ языка (алфавит);

Ø Элементарная конструкция;

Ø Выражение;

Ø Оператор.

Символы языка – это основные неделимые знаки, в терминах которых пишутся все тексты на языке.

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

Элементарные конструкции – это минимальные единицы языка, имеющие самостоятельный смысл. Они образуются из основных символов языка.

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

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

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

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

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

Константа - в программировании - элемент данных, который занимает место в памяти, имеет имя и определенный тип, причем его значение никогда не меняется.

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

Тип переменных определяется типом данных, которые они представляют.

Тип данных - характеристика набора данных, которая определяет:

ü диапазон возможных значений данных из набора;

ü допустимые операции, которые можно выполнять над этими значениями;

ü способ хранения этих значений в памяти.

Различают следующие типы данных (рисунок 1.8):

ü простые типы данных: целые, действительные числа и др.;

ü составные типы данных: массивы, файлы и др.

 


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

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

Машинный язык - язык программирования, элементами которого являются команды компьютера, характеризующиеся:

- количеством операндов в команде;

- назначением информации, задаваемой в операндах;

- набором операций, которые может выполнить компьютер и др.

Конструкции машинного языка интерпретируются непосредственно аппаратурой.

Исходный модуль - согласно ГОСТ 19781-90 - программный модуль на исходном языке, обрабатываемый транслятором и представляемый для него как целое, достаточное для проведения трансляции.

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

Транслятор - в узком смысле - программа, преобразующая: программу, написанную на одном (входном) языке в программу, представленную на другом (выходном) языке.

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

Синтаксические определения могут быть заданы формальными или неформальным способами.

Существуют три формальных способа:

· металингвистическая символика, называемая Бэкуса - Наура формулами;

· синтаксические диаграммы;

· скобочные конструкции.

В последующем изложении будет использоваться неформальный способ.

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


1.6. Эволюция языков программирования

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

Парадигма – это новая модель конструирования программы и взаимодействия ее с данными. На рисунке 1.9 приведены основные парадигмы программирования, применяемые в настоящее время.

 

 


История термина

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

Термин «парадигма программирования» впервые применил Роберт Флойд в своей лекции[1] лауреата премии Тьюринга. Р. Флойд отмечает, что в программировании можно наблюдать явление, подобное парадигмам Куна, но, в отличие от них, парадигмы программирования не являются взаимоисключающими: если прогресс искусства программирования в целом требует постоянного изобретения и усовершенствования парадигм, то совершенствование искусства отдельного программиста требует, чтобы он расширял свой репертуар парадигм.

Таким образом, по мнению Роберта Флойда, в отличие от парадигм в научном мире, описанных Куном, парадигмы программирования могут сочетаться, обогащая инструментарий программиста.

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

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


Основные парадигмы программирования

Функциональная Процедурная à Объектно-ориентированная Логическая
     

Рисунок 1.9 – Основные языки программирования

 


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

Языки развиваются в сторону все большей и большей абстракции. И это сопровождается падением эффективности. Вопрос: а стоит ли этого абстракция? Стоит, так как повышение уровня абстракции влечет за собой повышение уровня надежности программирования. С низкой эффективностью можно бороться путем создания более быстрых компьютеров. Если требования к памяти слишком высоки, можно увеличить ее объем. Это, конечно, требует времени и средств, но это решаемо. А вот с ошибками в программах можно бороться только одним способом: их надо исправлять. А еще лучше ‑ не совершать. А еще лучше максимально затруднить их совершение. И именно на это направлены все исследования в области языков программирования. А с потерей эффективности придется смириться.










Последнее изменение этой страницы: 2018-04-12; просмотров: 182.

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