Язык Ада, 02 лекция (от 03 марта)
Материал из eSyr's wiki.
Лекция №2.
Системы типов данных Надежной называют ту программу, которая не содержит слишком много ошибок, которые критичны для ее эксплуатации. Т.е. синтаксические ошибки, которые отлавливает компилятор, - это не критичные ошибки, а если генерируется код, который работает не так, как предполагалось – это критичная ошибка. Будем рассматривать надежность как предсказуемость программы. Ошибки берутся от того, что люди выполняют множество сложной работы. Программа – это задание, которое должен выполнить некий автомат. В связи с этим возникают следующие проблемы:
- У автомата отсутствует модель мира, поэтому что написано, то и будет выполнено, а отнюдь не то, что имелось в виду. Семантический разрыв между тем, чем можно пользоваться и тем, что нужно для содержательной задачи.
- Неконтролируемый и лавинообразный рост объема и сложности, которая ставиться перед программной индустрией.
Как Адская философия помогает бороться с этими сложностями? Программирования – создание модели решаемой задачи в программе. Все средства языка должны быть нацелены на то, чтобы описать задачу в понятных программисту терминах и чтобы эта модель была работающей. Если имеется слишком мелкий инструмент, то сначала создается необходимый инструментарий более высокого уровня для удобного использования этих инструментов для решаемой задачи. Надежный язык такой, в котором запрещено все, что не разрешено языком. При вводе в программе некой сущности, необходимо определить все свойства этой сущности и при использовании этой сущности должна отсутствовать возможность использовать эту сущность не по назначению. При введении какой-то сущности в программе должна иметься возможность определять ровно то, что действительно необходимо. В стандарте языка Ада прописано то, какие ошибки могут возникать, и какой должен быть механизм обработки соответствующих ошибок. Концепция строгой типизации Тип данных – определение содержательной роли объекта данных в решении задачи. Допустим, в программе для летального аппарата есть переменные, относящиеся к высоте полета и к скорости полета. Обе переменные являются вещественными типами. Множество значений переменных совпадают, множество операций – тоже. Но будет глупо, если присвоить высоту скорости. Это может произойти, если рассматривать тип данных как совокупность множества значений и множества операций. Если рассматривать тип данных как содержательную роль в модели, то этого произойти не может. Рассмотрим пример, когда задается тип данных с плавающей точкой, в котором указывается, сколько знаков после запятой следует учитывать. В Аде существует правило, которое гласит, что если программа откомпилировалась без ошибок, то именно такая точность будет у соответствующей переменной. Это лучше, чем если бы программа откомпилировалось без ошибок, но реальная точность переменной была бы ниже заявленной. Тип должен быть задан при определении данного объекта данных путем указания имени ранее определенного типа. Для всех операций должен быть определен типы параметров и результаты, если это функции, также при помощи указания имени ранее определенных типов. При вызове любой операции проверяется соответствие типов фактический параметров операции для формальных параметров. Присваивание также считается операцией. Все типы определяются статически, при компиляции все известно, неявного преобразования типов нет. Эти правила не имеют исключений. Пример программы про фрукты, яблоки и апельсины [код] Новый тип определяется с помощью конструкции is new из уже ранее определенного типа. «+» - операция, у нее есть типы параметров и результат, «=» - тоже операция, слева и справа должны быть данные одного типа. Нельзя присваивать, например, яблоки апельсинам. Нельзя сравнить яблоки с апельсинами. У каждого типа есть набор предопределенных операций. Например, для целого типа это арифметика, присваивание и сравнение. Эти предопределенные операции как будто неявным образом определены сразу после определения типа. Если нужно сложить яблоки с апельсинами, то можно их рассмотреть как фрукты и тогда сложить, но это нужно указывать явно. При соблюдении некоторых ограничений можно использовать тип данных в не своей роли, но это нужно сказать явно(явное преобразование типов). Преобразования типов возможны между родственными типами. Есть универсальный целый тип – константы. Константы могут быть неявно преобразованы к другому типу. Неявно преобразовать целую константу можно только к целому типу. В Аде существует пакет, который называется Standard, в котором определены такие вещи, как тип boolean, тип integer и тд, которые описаны так же, как и любые пользовательские типы. Подтипы Допустим, что мы пишем автопилот для чего-то, что летает. У этой летающей штуки есть скорость. Пусть она будет плавающим типом. Конструктивно она может перемещаться от 0 до 500 м/c. Но в разумных пределах лучше летать со скоростью до 250м/c, которая будет безопасной скоростью. С помощью конструкции subtype можно определить ограничения на множества значения уже существующего типа скорость. Допустим, что существует функция, которая возвращает текущую скорость. Скорость должна быть безопасной, поэтому возвращает она подтип безопасная скорость. Если в момент, когда вызывают эту функцию, она возвращает значение, которые не входит в множество безопасной скорости, то возбуждается предопределенное исключительная ситуация. Проверка значений подтипов происходит во время выполнения задачи. Массивы Массивы определяются с помощью ключевого слова range(n). Индекс n должны быть дискретным типом. В Аде имеется возможность задавать неограниченные массивы. Например, можно определить неограниченный тип строка. Но для создания фактического массива типа строка, необходимо предусмотреть ограничения диапазона возможных значений индекса. При сравнении двух строк разной длины проверка на соответствие размерам будет происходить во время выполнения программы. Ограничение неограниченного типа происходить за счет механизма подтипов.