И.Г. Головин - Конспект лекций по курсу Языки программирования (1161120), страница 14
Текст из файла (страница 14)
До объектных языков не было адекватных ИП. РазвитиеОЯП и ИП шло параллельно.WIMP (Window Icon Mouse Pointer)Общие принципы: 1970г., Xerox PARC.Николаус Вирт был там и проникся восхищением, немедленно начал изобретать своюрабочую станцию: Модула 2, Оберон. В 1972г – появился SmallTalk.76Переход системы из состояния в состояние происходит скачкообразно, это можно назватьсобытием.
С окном должен быть связан тип данных. События: клавиатура, мышь, таймер.Для события должен быть обработчик.Клавиатура: номер клавиши (скан-код), нажата/не нажата, клавиши-индикаторы (Ctrl).Общее у событий – момент системного времени, больше ничего общего у событий нет. Длярешения этих задач служит объединение типов.Язык C: union, язык Паскаль/Модула 2: записи с вариантами.Общий синтаксис:recordОбщая частьВариантная частьendcase Дискриминант ofM1: (вариант 1);M2: (вариант 2);…Mn: (вариант n);else: (вариант n+1)end;Дискриминант может быть 2ух видов: имя:тип или тип.1) Некое поле внутри записи.ОбщаячастьИмя дискриминантаВариант 1Вариант 2…Вариант NВ Модула 2: метки M1,…,Mn.
Также есть else – часть (синтаксический сахар).Такие события называются дискриминированными. Применительно к событиямдискриминантом может служить тип события.2) типrecordcase Boolean oftrue: (i: integer);false: (bits: packed array[1..48] of Boolean);end;Версия на стандартном Паскале: не мобильна (неразмеченное объединение).В языке Си разрешены только неразмеченные объединения.77Программисты на Windows знают VARIANT – запись.VARIANTUnion {Struct {short vt;Bool vt_bool;} vt_bool;Struct {Short vt;Pword vt_IM;} vt_IM;}В языке Ада запись с вариантами имеет неограниченный тип.Type Event (et:EventType) isrecordОбщая частьcase et:EventType ofwhen KBEvent => … |when MousePressEvent => … |…when others => …end record;X:Event – если это не параметр процедуры => ошибка.X:Event(KBEvent);new Event(MousePressEvent);Отвести под переменную память можно, только указав дискриминант.В любом языке 60-70 годов есть записи с вариантами, а в ООП появилось наследование,заменяющее их.
Зачем мы изучаем записи с вариантами? Языки умирают, но приемыпрограммирования остаются. Например, диспетчеризация (механизм динамическоговыбора). В языке C++ - механизм виртуальных функций. В языке Java все диспетчеризуется.Недостатки:1) Можем ошибочно сменить поле типа2) Большой switch – плохо в C++. Плохой стиль. Причина в важности устойчивостиизменений программного продукта. Сопровождать ООП очень удобно, а вотпросматривать большой код и исправлять switch’и – нет.Поэтому в ООП должна отсутствовать диспетчеризация по полю типа. В современныхпрограммах нужно этого избегать.Строки (String)78Область значений – произвольная последовательность символов.Массив – непрерывная последовательность данных, строка же не обязана бытьнепрерывной (это зависит от реализации).
Например, арабский текст. Его беда в том, что онсодержит различные элементы и всегда разделен на сегменты, каждый из которыхнеобходимо читать по-своему. Поэтому реализовать хранение такого текста с помощьюнепрерывной последовательности данных просто невозможно.В Delphi, C#, Java => string – массив.Зачем нужен тип string, если есть char []s? Зачем нужны эти 2 типа: Vector<T>,basic_string<T>? Чем отличается библиотечный конструктор от базисного? Библиотечныйне зависит от транслятора => его можно отрезать. String маскируется под библиотечный, ноего семантика зашита в транслятор. String – тип из базиса.C++ настолько богатый язык, что с помощью библиотек можно построить string,неуступающий встроенным string из Java и C#.В STL есть Vector<T>, basic_string<T>, имеющие схожие операции push_back(), size().
Но этитипы отличаются конкатенацией, а также операцией индексирования. Операцияиндексирования возвращает ссылку для vector<T>, но string[] возвращает char. Stringявляется неизменяемым в большинстве индустриальных ЯП.string s=””; string line;while ((line = Console.ReadLine()) !=null)s += line;Неэффективный код! Куча времени будет уходить на дефрагментацию.string line; var sb = new StringBuilder();shile ((line = Console.ReadLine()) !=null)sb.Append(line);string s = sb.ToString();Существенно более эффективно!Сложность в распределении памяти под строки состоит в том, что алгоритм распределениядолжен быть различным для маленьких и больших строк.Другие структурные базисные типыРанее мы рассмотрели: массивы, записи, строки (динамические).Паскаль (1970г.): существовала куча типов (множества, таблицы, файлы), но строк среди нихне было (динамических).Множества удобно использовать, например, в алгоритме «Решето Эратосфена» (поискапростых чисел).
Но минус множеств Паскаля – их маленький размер (до 256).set of T;|T|<=NBITSET = SET OF [0..N-1];в Модула 2В языке Оберон нет множеств вида set of T, т.к. нет типа, который мог послужить в качествебазового. Поэтому там остался просто set.79Таблица – это обобщение множества (в общем случае).Вывод: в современных ЯП базис упростился.ОПЕРАТОРНЫЙ БАЗИСОператор – это нечто, что обладает побочным эффектом. Машинные команды: вводавывода, пересылки, арифметико-логические, переходы. Ввод-вывод: прерогативабиблиотеки в современных ЯП.Пересылки => оператор присваивания (для процедурных ЯП)Арифметико-логические => выражение (в любом ЯП)Переходы => операторы управленияОператор присваивания – самый тяжелый, с точки зрения трансляции, оператор.1967г.
– “GoTo statements considered harmful” Дейкстра. Переломная статья впрограммировании. До 1967г. целью создателей ЯП было «понапихать» туда побольшевсего. Например, в языке Фортран существовало 4 оператора перехода, чтобы датьпрограммисту возможность для реализации своих намерений. Существовал термин – DSprograms (dish of spaghetti): программы были похожи на спагетти (нарисованныекарандашами переходы с одной строки на другую, переплетающиеся друг с другом).Оказалось, что хорошие программы содержат ограниченное число структур перехода.Фактически, статья Дейкстры положила начало новому направлению – структурированноепрограммирование (структурное программирование).
Структурное программирование –процесс разделения программы на уровни абстракции, а затем их последующаядетализация. С этой точки зрения оператор GoTo – запрещается.В 1969г. Вирт придумал ЯП, который выразил идеи структурного программирования, вкаждом следующем языке встречаются такие же структуры.Любой последовательный алгоритм можно записать с помощью:1) s1;s2 – последовательность2) while B do SОсновная идея Дейкстры состояла в том, чтобы писать программы сразу же в терминах этихструктур: блок, развилка и циклы.В языках появляется составной оператор – частный случай блока. Он применяется там, гдепо синтаксису подходит один оператор, а требуется несколько.
Отличие от блока состоит втом, что в блоке могут появляться локальные переменные.begin s1;…sn; end – составной оператор{объявление; операторы} – блокБлок – область видимости; тело функцииВыйти из блока тела функции нельзя.void f(){int i;…if (a>b) {80double i;…}…}В этом примере происходит скрытие. В языке C# компилятор в таких случаях выдаетпредупреждение – вынуждает поставить заглушку (new).Блок является не областью видимости, а средством группировки операторов.if B1 then if B2 then s1 else s2 – плохо (специально записано в одну строку)Существует проблема замыкания (непонятно какой else к какому if относится) – этосинтаксическая неоднозначность. Проблема была решена так, что else отнесется кближайшему if, иначе необходимы структурные скобки.В языке shell, например, отсутствует понятие составной оператор.Языки Ада, Модула-2, Оберон используют схему явного закрытия операторов.if B1 thenS11; S12; S13;end ifif B thenS1elseS2ndНа языке Си грамотно писать:if (B1)S1else if (B2)S2else if (B3)S3elseSNПричины этого: во-первых, пожалейте экран; во-вторых, наглядность.В языке Python отступы являются правилом.
Без их правильного использования нельзянаписать синтаксически корректную программу.Структурные операторыСтруктурные операторы – это такие операторы, которые содержат внутри себя другиеоператоры:РазвилкиЦиклыБлоки или составные операторыСоставной операторСоставной оператор – это последовательность операторов, объединенных в единуюконструкцию.81Пример (Паскаль)begin S1 … Sn endПримеры языков:Стандартный Паскаль,«паскалоиды» (например, Delphi)Модула 2ОберонАдаПоследние 3 языка особенны в отношении понятия составного оператора: в них также естьпонятие блока.Почему же они особенны? Ведь в стандартном паскале тоже есть понятие блока.Блок и составной операторЧто такое блок и чем он отличается от составного оператора?Блок – это область видимости.
В блоке могут быть объявления.Блок состоит из двух частей:1. Объявления локальных переменных2. ОператорыПонятие блока есть во всех языках. Более того, если рассматривать языки, опирающиеся наАлгол 60 (а это почти все современные языки), там не было составного оператора, но былблок.Языки C/C++ наследуют эту идеологию.Пример (C, C++){ объявления; операторы }Область видимости и область действия (как правило, они совпадают, но это не так дляфункциональных и некоторых современных языков) – это блок.Подчеркнем, что понимание разницы между блоком и составным оператором важно дляпринятия тех или иных решений о выборе языка решений.В Си-подобных языках: объявление блока является слишком жестким.В некоторых языках (таких, как Java и JavaScript) исчезает разница между объявлением иоператором.
Впервые это явление возникло в языке C++. Здесь конструктор (является иопределением, и оператором)Все эти языки поддерживают правило: опережающее объявление объектов.82Правило опережающего объявления объектовПравило опережающего объявления объектов имеет две цели.1. Утилитарная. Языки, поддерживающие это правило, проще транслировать. Можемупотреблять некоторое имя до его объявления. Как правило, большинствотрансляторов справляются с этим легко: на первом этапе выполняется лексическийанализ, включающий свертку имен; на втором этапе выполняется синтаксическийанализ, причем используемое имя уже известно.2.