Текущая версия |
Ваш текст |
Строка 1: |
Строка 1: |
- | [[Языки программирования, 11 лекция (от 10 октября)|Предыдущая лекция]] | [[Языки программирования, 13 лекция (от 17 октября)|Следующая лекция]]
| + | == From Ebaums Inc to MurkLoar. == |
- | | + | We at EbaumsWorld consider you as disgrace of human race. |
- | = Часть 1. Основные понятия традиционных процедурных ЯП = | + | Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated. |
- | == Глава 3. Операторный базис ЯП ==
| + | Dig yourself a grave - you will need it. |
- | | + | |
- | <div class="comment">В терминологии полный бардак. Нет согласия, как переводить computer science. Начиная с 60х годов, то, что слово «statement», в описании языка [[Algol|Algol 60]], стало эталоном языкового описания. «Assignment statement» — оператор присваивания. В русском языке появилась традиция переводить слово «statement» как «оператор». Иногда ещё употребляется термин «инструкция». Мы будем употреблять термин «оператор». Проблема в чём: проблем нет, есть оператор, есть операция (сложение, вычитание). Проблема была порождена [[C++]], где под оператором понимали то, что мы понимаем под словом операция. Есть переопределение операций.
| + | |
- | | + | |
- | В терминологии главное договориться. Мы будем следовать традициям [[Algol|Algol 60]] и под оператором будем понимать statement, операция — это операция.</div>
| + | |
- | | + | |
- | '''Операторный базис ЯП''' — то, какие операторы есть в ЯП.
| + | |
- | | + | |
- | <div class="comment">Операторный базис унифицирован больше всего. Причина историческая.</div>
| + | |
- | | + | |
- | === Пункт 1. Структурное программирование ===
| + | |
- | | + | |
- | <div class="comment">Кто-то отмечал, что strcutured programming переводится как структурированное программирование.</div>
| + | |
- | | + | |
- | История начинатся в [[1961]] году, когда ныне покойный Дейкстра опубликовал статью о вреде языка goto. Идея (казалось бы, бредовая): необходимо ограничитиь программиста в управлении, то есть, ограничеть возможности по управлению выполннием программы. Кажущаяся бредовость заключается в том, что до этого цель разработчика языка программирования дать как можно больше возможностей программисту.
| + | |
- | | + | |
- | <div class="comment">Ограничение возможностей программиста влияет благотворно.</div>
| + | |
- | | + | |
- | В [[Java]] нет goto. Но в Java он зарезервировано, чтобы изгнать это «слово из четырёх букв».
| + | |
- | | + | |
- | Разбиение операций на приватные и публичние тоже ограничение возможностей программиста.
| + | |
- | | + | |
- | Ситуация, когда програмиста ограничивают в выразительных возможностях иногда полезна.
| + | |
- | | + | |
- | Структурное программирование вредно представлять как программирование без goto. Это программирование в терминах уровней абстракций.
| + | |
- | | + | |
- | Есть три блока:
| + | |
- | # Подготовить
| + | |
- | # Выполнить
| + | |
- | # Завершить
| + | |
- | | + | |
- | Потом понижаем уровень абстракции до конкретных языках языка программирования, и операторы языка программирования — чёрные ящики.
| + | |
- | | + | |
- | Идея оказалась благотворной.
| + | |
- | | + | |
- | Довольно быстро все пришли к консенсусу, что структурное программирование полезно.
| + | |
- | | + | |
- | Современных программитстов обучают таким образом, что они программируют в терминах структурного программирования.
| + | |
- | | + | |
- | <div class="comment">Любимый пример лектора из опыта военной подготовки:<br />
| + | |
- | Читали там на [[Algol-60]]. Была программа, которую написал майор. Программа генерации перестановок. Сама по себе задача выеденного яйца не стоит. Проблема в том, что рекурсия не употреблялась, но там где-то на 9 строчек было 7 операций goto. Ив течении половины лекции пытался объяснить, как она работает, и в итоге сказал «даю вам слово, это программа работает. Я её полночи проверял».</div>
| + | |
- | | + | |
- | Программы с интенсивным использованием goto стали называтьм DS-программы (dish of spagetti).
| + | |
- | | + | |
- | Самый главный оператор — оператор присваивания. Самое интересное с операторе присваивания — согласование типов, а это уже ТД.
| + | |
- | | + | |
- | Основные операторы классифицируются на несколько видов:
| + | |
- | # Оператор присваивания
| + | |
- | # Управляющий оператор
| + | |
- | # Специальные операторы
| + | |
- | В современных языках оитсустствуют такие вещи, как операторы ввода-вывода.
| + | |
- | | + | |
- | Существенно оказало влияние то, какие существуют операторы управления.
| + | |
- | | + | |
- | # Операторы ветвления. Делятся на
| + | |
- | ## Ветвления
| + | |
- | ## Дискретные
| + | |
- | ## Многовариантные
| + | |
- | # Циклы
| + | |
- | ## С предусловием
| + | |
- | ## С постусловием
| + | |
- | ## С фиксированны числом повторений
| + | |
- | ## С управлением пользователем
| + | |
- | # Переходы
| + | |
- | # Блок
| + | |
- | | + | |
- | Переходов очень много вариантов.
| + | |
- | | + | |
- | А можно обойтись без goto?
| + | |
- | | + | |
- | Была опубликована статья: любую управляющую структуру можно свести к трём, точнее, двум структурам — цикл и последовательность (третья структура, условие — цикл не более чем с одной операцией)
| + | |
- | | + | |
- | Более того — программы с любыми комбинациями условий можно свести к композициями циклов. Создавались программы, которые позволяли переводить программы с goto в программы без goto.
| + | |
- | | + | |
- | В ... году ехидный Кнут написал статью «структурное программирование с использованием goto». Знаменитая цитата: «иногда употребелние всяких слов из четырёх букв типа goto является уместном даже в самом лучшем обществе».
| + | |
- | | + | |
- | === Пункт 2. Ветвление ===
| + | |
- | | + | |
- | ==== Двухвариантное ветвление ====
| + | |
- | | + | |
- | '''([[Algol]])'''
| + | |
- | '''([[Pascal]])'''
| + | |
- | if B then
| + | |
- | S1
| + | |
- | else
| + | |
- | S2
| + | |
- | | + | |
- | Отличаются ЯП по тому, стоавить then или нет, ставить скобки или нет. ЯП с точки зрения управляющих конструкций делятся на две категории — с терминаторами и без терминаторов. В ЯП без терминаторов — неявное завершение условия.
| + | |
- | | + | |
- | Проблема, которую заметил Дональд Кнут:
| + | |
- | | + | |
- | if B1 then if B2 then S1 else S2
| + | |
- | | + | |
- | Вопрос, когда выполняется S2, к какому if прижимается else. Более того, в первой реализации [[Algol-60]] эту проблему просмотрели, а Кнут её первый заметил.
| + | |
- | | + | |
- | В языках без терминаторов нужно использовать составные операторы («begin … end», «{ … }»)
| + | |
- | | + | |
- | В языках с явными терминаторами явно обозначается конец. Примеры — [[Ada]], [[Modula-2]], [[Oberon]]. В этих языках отсутствует понятие составного языка как такового.
| + | |
- | | + | |
- | if B then S1 else S2 end if;
| + | |
- | | + | |
- | <!-- Бейсик тоже удовлетворяет. - ??? -->
| + | |
- | | + | |
- | Такие языки синтаксически более элегантны. Проблема языков с неявными операторами в том, что в том месте, где пропущена скобка, возникают вложенные операторы. В ЯП с явным терминатором синтаксический анализ проводить проще, и ошибки искать проще. Но тут сразу возникает другая проблема.
| + | |
- | | + | |
- | ==== Многовариантное ветвление ====
| + | |
- | | + | |
- | Есть несколько вариантов, частным случаем которого является дискретное ветвление. В общем случае с каждым оператором связано своё условие. В некоторых ЯП (например, в Ada) есть оператор select:
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | select
| + | |
- | when B1 => S1
| + | |
- | when B2 => S2
| + | |
- | ...
| + | |
- | when Bn => Sn
| + | |
- | else Sn+1;
| + | |
- | end select;
| + | |
- | | + | |
- | В общем случае в ЯП такой структуры нет, она очень легко моделируется с помощью if:
| + | |
- | | + | |
- | if (B1)
| + | |
- | S1
| + | |
- | else if (B2)
| + | |
- | S2
| + | |
- | else if (B3)
| + | |
- | S3
| + | |
- | else Sn+1
| + | |
- | | + | |
- | Такой способ записи удобен для языков, где нет явного терминатора. В языках с явным терминатором надо писать в конче кучу end if. Простое синтаксическое решение ведёт к появлению специального оператора.
| + | |
- | | + | |
- | В [[Modula-2]]: ELSIF, чтобы подчеркнуть, что это не ELSE IF.
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | if B then
| + | |
- | seg1
| + | |
- | elseif (b2)
| + | |
- | seg2
| + | |
- | ...
| + | |
- | else
| + | |
- | segn
| + | |
- | end if;
| + | |
- | | + | |
- | Подобные конструкции должны появляться во всех языках с явным терминатором.
| + | |
- | | + | |
- | ==== Дискретный оператор ветвления ====
| + | |
- | | + | |
- | Начиная с [[Pascal]] и [[C]], есть дискретное ветвление, ибо оно появляется настолько часто, что для этого появляются специальные управляющие структуры.
| + | |
- | | + | |
- | '''([[Pascal]])'''
| + | |
- | case E of
| + | |
- | 0: seg1; { в [[Modula-2]] и [[Oberon]] вместо «;» d этом случае используется «|» }
| + | |
- | 1..3: seg2;
| + | |
- | 4, 6..9 : seg3;
| + | |
- | else
| + | |
- | segN;
| + | |
- | end;
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | сase E of
| + | |
- | when V1 => seg1 — знаков-терминаторов не нужно, ибо им будет либо следующий when, либо end
| + | |
- | when V2 => seg2
| + | |
- | ...
| + | |
- | when others => segN
| + | |
- | end case
| + | |
- | | + | |
- | Этот синтаксис похож на синтакси записей с вариантами.
| + | |
- | | + | |
- | Если бы оператор переключателя отсутствовал, то это был бы миинус языка, так как он как минимум нужен для работы с записями с вариантами.
| + | |
- | | + | |
- | Опепраторы с переключателями могут быть более эффективны, чем каскад из if или select.
| + | |
- | | + | |
- | Если память не очень жалко, то можно сделать таблицу адресов переходов.
| + | |
- | | + | |
- | Единственным уроодом выглядит переключатель языка [[C]]:
| + | |
- | | + | |
- | <!-- //педедыв -->
| + | |
- | | + | |
- | <!-- Лектор: Я считаю, что университет не должен быть ангажирован, но тем не менее, я не являюсь масдащиком, и как Цезарь, преподаватель должен быть вне подозрений. -->
| + | |
- | | + | |
- | С точки зрения большинства экспертов, синтаксис [[C]] один из самых неудачных. Хуже только [[FORTRAN]]. Но, тем не менее, он окозался настолько популярным, что многие языки имеют синтаксические корни [[C]].
| + | |
- | | + | |
- | <div class="comment">На экзамене за синтаксические ошибки лектор ругать не будет.</div>
| + | |
- | | + | |
- | Синтаксис:
| + | |
- | | + | |
- | '''([[C]])'''
| + | |
- | switch (e) S
| + | |
- | | + | |
- | Обычно S — составной оператор. В котором есть метки специального вида:
| + | |
- | | + | |
- | Switch(e)
| + | |
- | {
| + | |
- | case val:
| + | |
- | ...
| + | |
- | default:
| + | |
- | ...
| + | |
- | }
| + | |
- | | + | |
- | if e = val then goto val;
| + | |
- | | + | |
- | В этом уродство. Если не нашли и есть default, то goto default.
| + | |
- | | + | |
- | Проблема в том, что только один goto.
| + | |
- | | + | |
- | Основная ошибка, которую делает даже лектор, и не потому что он крутой, а потому что он 15 лет программирует на [[C]] с перерывами на [[Delphi]] и другие языки: забывание break. В некоторых случаях отсутствие break бывает необходимо, но лектор использовал её всего несколько раз, и то неправильно.
| + | |
- | | + | |
- | Языки, которые основаны на [[C]]: В [[Java]] goto нет, но идиотизм с break остался. В [[C#]] брейк писать надо, но не писать его нельзя, дабы обеспечить мобильность навыков, знаний. В [[Java]] break может содержать метку, а метка может помечать начало цикла, и это позволяет делать break более чем на один уровень.
| + | |
- | | + | |
- | После обсуждения операторного базиса отметим, что [[Pascal]] был написан Виртом, который был одним из основателей структурного программирования. Набор управляющих конструкций стандартного Pascal кочует из однго языка в другой.
| + | |
- | | + | |
- | ==== Циклы ====
| + | |
- | | + | |
- | '''([[Pascal]])'''
| + | |
- | while B do
| + | |
- | S;
| + | |
- |
| + | |
- | repeat
| + | |
- | S1;
| + | |
- | ...
| + | |
- | Sn;
| + | |
- | until B;
| + | |
- | | + | |
- | '''([[C]])'''
| + | |
- | while (B)
| + | |
- | S;
| + | |
- |
| + | |
- | do
| + | |
- | S
| + | |
- | while (B)
| + | |
- | | + | |
- | Мэтры согласислись, что этого достаточно, но не тут-то было. Кнут в статье «структрное программирование с goto» отметил, что структура программы должна отвечать структуре алгоритма, а он структурен, но алгоритм не всегда укладывается в while и do while.
| + | |
- | | + | |
- | Алгоритм:
| + | |
- | * Подготовить ввод
| + | |
- | * Если конец файла, то выйти иначе обработать и в начало.
| + | |
- | | + | |
- | Тут выход из середины цикла. Это можно смоделировать циклами до, но это корёжит структуру. Тут лучше использовать goto.
| + | |
- | | + | |
- | <div class="comment">Лектор, будучи студентом писал метакомпилятор на [[Fortran-66]] (там отсутствовал логический оператор, отсутствовали циклы, но было 4 оператора перехода), который отвечсал структурному программированию, но был на goto.</div>
| + | |
- | | + | |
- | ==== Циклы, управляемые пользователем ====
| + | |
- | | + | |
- | Рассмотрим на примере языков Вирта, как являющихся минимальными.
| + | |
- | | + | |
- | Есть
| + | |
- | | + | |
- | WHILE B DO
| + | |
- | S1
| + | |
- | END
| + | |
- | | + | |
- | А есть
| + | |
- | | + | |
- | LOOP
| + | |
- | S1 ... SN
| + | |
- | END
| + | |
- | | + | |
- | В [[Modula-2]] квазипараллельное программирование: бесконечные циклы не ошибка, они иногда необходимы, например, для фоновых процессов. Только в LOOP может использоваться EXIT. EXIT то же самое, что и break в [[C]], только у него более широкое поле деятельности.
| + | |
- | | + | |
- | Наиболее универсальная концепция цикла в языке Ада:
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | loop
| + | |
- | S1 ... Sn
| + | |
- | end loop;
| + | |
- | | + | |
- | есть специальная конструкция:
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | [when B => ] EXIT;
| + | |
- | | + | |
- | аналог
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | if B then
| + | |
- | exit;
| + | |
- | end if;
| + | |
- | | + | |
- | На этот loop может навёртывается while B do, который или перед loop, или перед end loop.
| + | |
- | | + | |
- | Ещё [[BASIC]].
| + | |
- | | + | |
- | Ada позволяет с помощью одной синтаксической конструкции промоделировать любые виды циклов.
| + | |
- | | + | |
- | Языки делятся на два класса:
| + | |
- | # C-подобные языки
| + | |
- | # Остальные — те языки, которые представлены в курсе, основаны или близки к Pascal
| + | |
- | | + | |
- | [[BASIC]]:
| + | |
- | | + | |
- | '''([[C]])'''
| + | |
- | for (e1; e2; e3)
| + | |
- | S
| + | |
- | | + | |
- | '''([[Pascal]])'''
| + | |
- | for i:=e1 to e2 do
| + | |
- | S;
| + | |
- | | + | |
- | '''([[Modula|Modula-2]])'''
| + | |
- | FOR I:=E1 TO E2 STEP E3 do
| + | |
- | ...
| + | |
- | END;
| + | |
- | | + | |
- | [[Oberon-2]]:
| + | |
- | | + | |
- | Вирт с пафосом в design notes: Так же сочтён излишним оператор for.
| + | |
- | | + | |
- | Но возникает необходимость где-то описывать локальные переменные, которые нужны только для того, чтобы индексировать массивы и т. д.
| + | |
- | | + | |
- | '''([[Ada]])'''
| + | |
- | for i in range do
| + | |
- | loop
| + | |
- | end loop;
| + | |
- | | + | |
- | Переменная i локализуется внутри цикла.
| + | |
- | | + | |
- | '''([[C++]])'''
| + | |
- | for(int i=0; ...)
| + | |
- | | + | |
- | Страуструп сказал, что некоторые вещи он сделал бы по-другому.
| + | |
- | | + | |
- | Дальше всех пошли создатели [[Visula Basic]] и [[C#]]:
| + | |
- | | + | |
- | foreach (T x in C) S
| + | |
- | | + | |
- | Для массивов данный оператор не особо нужен, но тем не менее, лучше ибо в for(int i=0; i<a.length; i++) {... a[i] ...} индексация медленнее, ибо проверки, а для foreach проверки не нужны. На самом деле, в современных ЯП появляются понятия рефлексии — в программе могут использоваться свойства программы. В [[C#]] — коллекция — то, что поддерживает интефейсом Enumerable, и если написать свой класс, то он тоже будет коллекцией и поддерживаться foreach. Этого в [[C++]] и более старых языках не было. Другой пример рефлексии — атрибуты в [[C#]].
| + | |
- | | + | |
- | <div class="comment">Осталось поговорить про переходы: есть операторы, которые являются частными случаями переходов, break и continue, return. Это не противоречит основным концепциям структруного программирования.</div>
| + | |
- | | + | |
- | {{Языки Программирования}}
| + | |
- | {{Lection-stub}}
| + | |