Императивы языка
Язык Ада поддерживает множество парадигм программирования, включая объектно-ориентированное программирование и некоторые элементы функционального программирования, но в его основе лежит простой сбалансированный процедурный/императивный язык, аналогичный C или Pascal.
На других языках
Одно важное различие между Адой и таким языком, как C, заключается в
том, что операторы и выражения очень четко различаются. В Ада, если вы
попытаетесь использовать выражение, там, где требуется оператор, ваша
программа не будет скомпилированна. Это правило реализует
полезный стилистический принцип: преднозначение выражений в вычислении
значений, а не для в побочных эффектах. Оно также может предотвратить
некоторые ошибки программирования, такие как ошибочное использование
операции проверки на равенства =
вместо операции присваивания
:=
в операторе присваивания.
Hello world
Вот очень простая императивная программа Ада:
Текс программы, как мы предполагаем, находится в исходном файле greet.adb
.
Если мы соберем программу с помощью компилятора GNAT и запустим ее, то получим ожидаемый результат.
$ gprbuild greet.adb
using project file [...]_default.gpr
Compile
[Ada] greet.adb
Bind
[gprbind] greet.bexch
[Ada] greet.ali
Link
[link] greet.adb
$ ./greet
Hello, World!
$
В вышеупомянутой программе есть несколько примечательных вещей:
Подпрограмма в Аде может быть либо процедурой, либо функцией. Процедура, как показано выше, не возвращает значение при вызове.
with
используется для ссылки на внешние модули, которые необходимы в процедуре. Это похоже наimport
в разных языках или примерно похоже на#include
в C и C++. Позже мы разберемся в деталях их работы. Здесь мы запрашиваем стандартный библиотечный модуль, пакетAda.Text_IO
, который содержит процедуру печати текста на экране:Put_Line
.Greet
- это процедура и основная точка входа в нашу первую программу. В отличие от C или C++, его можно назвать как угодно по вашему усмотрению. Построитель должен знать точку входа. В нашем простом примере gprbuild, построитель GNAT, будет использовать файл, который вы передали в качестве параметра.Put_Line
- это такая же процедура, как иGreet
, за исключением того, что она объявлена в модулеAda.Text_IO
. Это Ада-эквивалентprintf
в Си.Комментарии начинаются с
--
и продолжаются до конца строки. Многострочные комментарии отсутствует, то есть невозможно начать комментарий в одной строке и продолжить его в следующей строке. Единственный способ создать несколько строк комментариев в Аде - это использовать "--
" в каждой строке. Например:
-- We start a comment in this line...
-- and we continue on the second line...
На других языках
Процедуры аналогичны функциям в C или C++, которые возвращают значение
void
. Позже мы увидим, как объявлять функции в Аде.
Вот вариация примера «Hello, World»:
В этой версии используется конструкция Аді, известное как спецификатор
использования (use
clause),
которая имеет форму use
имя-пакета. Как видно на вызове Put_Line
,
эффект заключается в том, что на объекты из указанного пакета можно ссылаться
напрямую – нет необходимости использовать имя-пакета. как префикс.
Условный оператор
В этом разделе описывается условный оператор if
в Аде, и вводятся
некоторые другие основные возможности языка, такие как целочисленный
ввод-вывод, объявления данных и виды параметров подпрограммы.
Условный оператор if
в Аде довольно неудивителен по форме и функции:
Оператор if
в простейшей форме состоит из зарезервированного
слова if
, условия
(которое должно быть логическим значением), зарезервированного слова then
и непустой последовательности операторов (часть then
), которая
выполняется, если условие вычисляется как True, и окончивается end if
.
Этот примере объявляет целочисленную переменную N, запрашивает у пользователя целое число, проверяет, является ли значение положительным, и, если да, отображается значение целого числа, за которым следует строка "является положительным числом" (is a positive number). Если значение не является положительным, то процедура не выводит ничего.
Тип Integer является предопределенным типом со знаком, и его диапазон зависит от архитектуры компьютера. На типичных современных процессорах целое число имеет 32-разрядный знак.
Пример иллюстрирует некоторые основные функциональные возможности для
целочисленного ввода-вывода. Соответствующие подпрограммы находятся в
предопределенном пакете Ada.Integer_Text_IO
и включают процедуру
Get
(которая считывает число с клавиатуры) и процедуру Put
(которая отображает целое значение).
Вот небольшое изменение в примере, которое иллюстрирует оператор if
с
частью else
:
В этом примере, если входное значение не является положительным, то программа отображает значение, за которым следует строка "не является положительным числом" (is not a positive number).
Наш последний вариант иллюстрирует оператор if
с elsif
частями:
В этом примере ожидается, что пользователь введет целое число от 0 до
360 включительно, и отобразит, какому квадранту или оси соответствует
значение. Операция in
в Аде проверяет, находится ли скалярное значение в
указанном диапазоне, и возвращает логический результат. Эффект
программы должен быть очевиден; позже мы увидим альтернативный и более
эффективный стиль для достижения того же эффекта используя оператор выбора
case
.
Ключевое слово elsif
в Аде отличается от C или C ++, где вместо него будут
использоваться блоки else .. if
. И еще одно отличие - это наличие конца
end if
в Аде, что позволяет избежать проблемы, известной как «висящий else»
(dangling else).
Циклы
У Ада есть три способа записи циклов. Каждый из них отличается от циклов for в C / Java / Javascript тем, что обладает более простыми синтаксисом и семантикой в соответствии с философией Ада.
Циклы for
Первый форма цикла - это цикл for
, который позволяет выполнять итерацию
по дискретному диапазону.
Исполнение этой процедуры дает следующий результат:
Hello, World! 1
Hello, World! 2
Hello, World! 3
Hello, World! 4
Hello, World! 5
Несколько моментов, которые следует отметить:
1 .. 5
- это дискретный диапазон, от1
до5
включительно.Параметр цикла
I
(имя произвольное) в теле цикла имеет значение в этом диапазоне.I
является локальным для цикла, поэтому вы не можете ссылаться наI
вне цикла.Хотя значение
I
увеличивается на каждой итерации, с точки зрения программы оно является константой. Попытка изменить его значение является незаконной; компилятор отклонит такую программу.Integer'Image
- это функция, которая принимает целое число и преобразует его в строку. Это пример языковой конструкции, известной как атрибут, обозначенной синтаксисом'
, который будет рассмотрен более подробно позже.Символ
&
является оператором конкатенации для строковых значений.end loop
обозначает конец цикла
"Шаг" цикла ограничен 1 (направление вперед) и -1 (назад). Чтобы
выполнить итерацию в обратном направлении по диапазону, используйте
ключевое слово reverse
:
Исполнение этой процедуры дает следующий результат:
Hello, World! 5
Hello, World! 4
Hello, World! 3
Hello, World! 2
Hello, World! 1
Границы цикла for
могут быть вычислены во время выполнения; они
вычисляются один раз, перед выполнением тела цикла. Если значение
верхней границы меньше значения нижней границы, то цикл вообще не
выполняется. Это относится и к reverse
циклам. Таким образом, в
следующем примере вывод не производится:
Цикл for
имеет более общую форму, чем та, которую мы проиллюстрировали
здесь; подробнее об этом позже.
Простой цикл
Самая простая форма цикла в Аде - это «голый» цикл, который образует основу других циклов Ада.
Этот пример имеет тот же эффект, что и Greet_5a
, показанный ранее.
Он иллюстрирует несколько концепций:
Мы объявили переменную с именем
I
междуis
иbegin
. Этот участок кода представляет собой зону описания. Ада чётко отделяет зону описания от секции операторов подпрограммы. Объявление может находиться в зоне описания, но не допускается в качестве оператора.Оператор простого цикла начинается с ключевого слова
loop
и, как и любой другой тип оператора цикла, завершается комбинацией ключевых словend loop
. Сам по себе это бесконечный цикл. Вы можете выйти из этого цикла с помощью оператора выходаexit
.Синтаксис для присваивания
:=
, а синтаксис для равенства=
. Их невозможно перепутать, потому что, как отмечалось ранее, в Аде операторы и выражения различны, а выражения не являются допустимыми операторами.
Циклы while
Последняя форма цикла в Аде - это цикл while
.
Условие вычисляется перед каждой итерацией. Если результат равен «ложь», то цикл завершается.
Эта программа имеет тот же эффект, что и предыдущие примеры.
На других языках
Обратите внимание, что Ада имеет иную семантику, чем языки на основе C, связанную с условием цикла while. В Ада условие должно быть логическим значением, иначе компилятор отклонит программу; условие не может быть целым числом, которое расценивается как истинное или ложное в зависимости от того, является ли оно ненулевым или нулевым.
Оператор выбора
Оператор выбора case
в Аде аналогичен оператору switch
из C/C++,
но с некоторыми важными отличиями.
Вот пример, вариация программы, которая была показана ранее с
инструкцией if
:
Эта программа неоднократно запрашивает целочисленное значение, а
затем, если значение находится в диапазоне 0 .. 360
, отображает
соответствующий квадрант или ось. Если значение является целым числом
за пределами этого диапазона, цикл (и программа) завершаются после
вывода прощального сообщения.
Эффект оператора выбора аналогичен условному оператору в предыдущем примере, но оператор выбора может быть более эффективным, нет нужды выполнять несколько тестов диапазона.
Примечательные моменты в операторе выбора в Аде:
Выражение выбора (здесь переменная
N
) должно быть дискретного типа, то есть либо целочисленного типа, либо типа перечисления. Дискретные типы будут рассмотрены более подробно позже.Каждое возможное значение для выражения выбора должно быть охвачено уникальной ветвью оператора
case
. Это будет проверено во время компиляции.Ветвь может указывать одно значение, например
0
; диапазон значений, например1 .. 89
; или любая их комбинация (с разделителем |).Отдельно может быть задана конечная ветвь с ключевым словом
others
, которая охватывает все значения, не включенные в предыдущие ветки.Выполнение состоит из вычисления выражения выбора, а затем передачи управления последовательности инструкций в уникальной ветви, которая охватывает это значение.
Когда выполнение операторов в выбранной ветви завершено, управление возобновляется после последней ветви (после
end case
). В отличие от C, выполнение не попадает в следующую ветвь. Таким образом, в Аде не нужен (и не существует) операторbreak
.
Зоны описания
Как упоминалось ранее, Ада проводит четкое синтаксическое разделение между объявлениями, которые вводят имена для сущностей, которые будут использоваться в программе, и операторами, выполняющими обработку. Области в программе, в которых могут появляться объявления, называются зонами описания.
В любой подпрограмме участок кода между is
и begin
является
зоной описания. Там могут быть переменные, константы, типы,
внутренние подпрограммы и другие сущности.
Мы кратко упоминали объявления переменных в предыдущем подразделе.
Давайте посмотрим на простой пример, где мы объявляем целочисленную
переменную X
в зоне описания и выполняем инициализацию и
добавление к ней единицы:
Давайте рассмотрим пример вложенной процедуры:
Объявление не может использоваться как оператор. Если вам нужно объявить локальную переменную среди операторов, вы можете ввести новую зону описания с помощью блочного оператора:
Attention
Функция Get_Line
позволяет получать входные данные от пользователя и выдавать
результат в виде строки. Это более или менее эквивалентно функции scanf
C.
Она возвращает строку (типа String
), которая, как мы увидим позже,
является неограниченным типом массива.
Пока мы просто отмечаем, что,
если вы хотите объявить строковую переменную (с типом String
) и заранее не
знаете ее размер, вам необходимо инициализировать переменную во время ее
объявления.
Условные выражения
В Ада 2012 были введены выражения-аналоги условных операторов (if
и case
).
Условное выражение
Вот альтернативная версия примера приведённого выше; операторы if
заменены на if
выражения:
Выражение if
вычисляет одну из двух строк в зависимости от N и
присваивает это значение локальной переменной S.
Выражения if
в Аде аналогичны операторам if
. Однако есть
несколько отличий, следующих из того факта, что это выражение:
Выражения всех ветвей должны быть одного типа
Оно должно быть заключено в круглые скобки, если уже не охвачено ими
Ветвь
else
обязательна, если только следующее заthen
выражение не имеет логического значения. В этом случае ветвьelse
является необязательной и, если она отсутствует, по умолчанию аналогичнаelse True
.
Вот еще один пример:
Эта программа выдает 10 строк вывода, чередующихся слов "Нечетный" и "Четный" ("Odd" и "Even").
Выражение выбора
Аналогично выражениям if
, в Аде также есть выражения case
. Они работают
именно так, как вы и ожидали.
Эта программа имеет тот же эффект, что и в предыдущем примере.
Синтаксис отличается от операторов case
тем, что ветви разделены запятыми.