Volume(Radius, Height)
Примечание: Функцию можно также вызывать через процедурную переменную. Подробности можно найти далее в разделе "Процедурные типы".
Синтаксис вызова функции теперь расширен и допускает вместо идентификатора функции использовать десигнатор метода или уточненный идентификатор метода.
Пояснение по расширению процедурных операторов, которое можно найти в Главе 7 ("Операторы процедуры") применимо также к вызовам функции.
В режиме расширенного синтаксиса ($X+) вызовы функций можно использовать в качестве операторов, то есть результат вызова функции может отбрасываться.
Примечание: подробности можно найти в Главе 21 ("Расширенный синтаксис").
Конструкторы множеств
Конструктор (описатель) множества определяет значения множественного типа и получается путем записи выражений, заключенных в квадратные скобки ([]). Каждое выражение определяет значение множества.
╒═══╕ ╒═══╕
конструктор множества ─│ [ ├─┬──────────────────────────┤ ] ├────
╘═══╛ │ ‑ ╘═══╛
│ │
│ ┌──────────────────┐ │
└─│ группа элементов ├─┬┘
‑ └──────────────────┘ │
│ │
│ ╒═══╕ │
└───────┤ , │─────────┘
╘═══╛
┌───────────┐
группа элементов ─│ выражение ├─┬─────────────────────────────
└───────────┘ │ ‑
│ │
│ ╒═══╕ ┌─────────┐ │
└─│ ..├──│выражение├──┘
╘═══╛ └─────────┘
Обозначение [ ] означает пустое множество, тип которого совместим по присваиванию с типом любого множества. Любая группа элементов, описанная, как х..y, объявляет элементами множества все значения в диапазоне х..y. Если х больше, чем y, то х..y не описывает никаких элементов и обозначает пустое множество.
В конкретном описателе множества все значения выражения в группах элементов должны быть одного перечислимого типа.
Приведем некоторые примеры конструкторов множеств:
[red, C, green]
[1,5,10..K mod 12, 13, 23]
['A'..'Z', 'a'..'z', Chr(Digit+48)]
Приведение типа значений
Тип выражения можно изменить на другой тип с помощью приведения типа значений.
┌───────────┐ ╒═══╕ ┌─────────┐ ╒═══╕
приведение ────│идент. типа├───│ ( ├───│выражение│───│ ) ├──
типа значений └───────────┘ ╘═══╛ └─────────┘ ╘═══╛
Тип выражения и задаваемый тип должны оба иметь перечислимый тип или тип указателей. Для перечислимых типов результирующее значение получается путем преобразования выражения (и возможной проверки на нахождение в допустимых границах). Преобразование может привести к усечению или увеличению размера исходного значения в том случае, если вновь определяемый тип отличается от типа выражения. В том случае, когда значение расширяется, его знак всегда сохраняется. Таким образом, значение является расширяемым по знаку.
Синтаксис приведения типа значений почти совпадает с синтаксисом приведения типа переменных (см. раздел "Приведение типа переменных" в Главе 4). Однако при приведении типа значений операции производятся со значениями, а не с переменными и, таким образом, могут не участвовать в ссылках на переменные. То есть за приведением типа значения не обязательно следуют квалификаторы. В частности, приведение типа значений не должно встречаться в левой части оператора присваивания.
Некоторые примеры приведения типа значений включают в себя:
Intereg('A')
char(48)
boolean(0)
Color(2)
IntPtr(@Buffer)
BytePtr(Ptr($40,$49)
Процедурные типы в выражениях
В общем случае использование процедурной переменной в операторе или выражении означает вызов процедуры или функции, хранящейся в этой переменной. Однако, имеется исключение. Когда Турбо Паскаль видит, что процедурная переменная находится в левой части оператора присваивания, он знает, что правая часть должна представлять собой процедурное значение. Рассмотрим в качестве примера следующую программу:
type
IntFunc = function: Integer;
var
F: IntFunc;
N: Integer;
function ReadInt: Integer; far;
var
I: Integer;
begin
Read(I);
ReadInt := I;
end;
begin
F := ReadInt; { присваивание процедурного значения }
N := ReadInt; { присваивание результата функции }
end.
Первый оператор основной программы присваивает процедурное значение (адрес процедуры) ReadInt процедурной переменной F, второй оператор вызывает ReadInt и присваивает N возвращаемое значение. Различие между получением процедурного значения или вызовом функции осуществляется по типу переменной, которой присваивается значение (F или N).
К сожалению, есть ситуации, когда компилятор не может определить из контекста желаемое действие. Например, в следующем операторе для компилятора не очевидно, что нужно сделать: сравнить процедурное значение в F с процедурным значением ReadInt, чтобы определить, что F указывает в данный момент на ReadInt, или вызвать F и ReadInt, а затем сравнить возвращаемые значения:
if F = ReadInt then
WriteLn('Equal');
Однако, стандартный синтаксис Паскаля определяет, что вхождение в выражение идентификатора функции означает вызов этой функции, поэтому в результате предыдущего оператора будет выполнен вызов F и ReadInt, а затем будут сравниваться возвращаемые значения. Чтобы сравнить процедурное значение в F с процедурным значением в ReadInt, нужно использовать следующую конструкцию:
if @F = @ReadInt then
WriteLn('Equal');
При применении к процедурной переменной, идентификатору процедуры или функции операции получения адреса @ эта операция предотвращает вызов компилятором процедуры и в то же время преобразует аргумент в указатель. Таким образом, @F преобразует F в нетипизованный указатель-переменную, которая содержит адрес ReadInt. Для определения того, что F ссылается на ReadInt можно сравнить два значения-указателя.
Для получения адреса в памяти процедурной переменной, а не того адреса, который в ней хранится, нужно использовать двойную операцию получения адреса @@. Например, @P означает преобразование P в нетипизованный указатель-переменную, а @@P означает возвращение физического адреса переменной P.