Spec-Zone.ru › Ada 2022
Руководство по Ada (Ada 2022)

4.5.10 Выражения сокращения

Выражения сокращения предоставляют способ отображения или преобразования набора значений в новый набор значений, а затем обобщения значений, полученных путём применения операции для сведения набора к одному значению результата. Выражение сокращения представляется как ссылка_на_атрибут атрибутов сокращения Reduce или Parallel_Reduce.

Синтаксис

ссылка_на_атрибут_сокращения ::=
последовательность_значений'обозначение_атрибута_сокращения
| префикс'обозначение_атрибута_сокращения
последовательность_значений ::=
'[' [параллельно[(указание_на_блок)] [указание_на_аспект]]
связь_элемента_повторного_применения ']'
обозначение_атрибута_сокращения ::=
сокращение_идентификатор(указание_на_сокращение)
указание_на_сокращение ::= редуктор_имя, начальное_значение_выражение
Связь элемента_повторного_применения последовательности значений не должна содержать ключ_выражение, а также не должно содержать указание_на_параметр_цикла с ключевым словом обратный.
Указание на_блок, если таковое имеется, в последовательности_значений должно быть целым_выражением.

Правила разрешения имён

Ожидаемый тип для ссылки_на_атрибут_сокращения должен быть одним нелимитированным типом.
В остальной части данного подраздела мы будем ссылаться на нелимитированные подтипы Value_Type и Accum_Type ссылки на_атрибут_сокращения. Эти подтипы и интерпретации имён имя и выражения ссылки на_атрибут_сокращения определяются следующими правилами:
  • Accum_Type является подтипом ожидаемого типа ссылки на_атрибут_сокращения.
  • Подпрограмма редуктора соответствует одному из следующих описаний:
функция Reducer(Accumulator : Accum_Type;
Value : Value_Type) return Accum_Type;
процедура Reducer(Accumulator : in out Accum_Type;
Value : in Value_Type);
  • Имя редуктор_имя в указании_на_сокращение обозначает подпрограмму редуктора.
  • Ожидаемый тип выражения начальное_значение_выражение указания_на_сокращение — подтип Accum_Type.
  • Ожидаемый тип выражения связи_элемента_повторного_применения последовательности_значений — подтип Value_Type.

Правила законности

Если ссылка на_атрибут_сокращения имеет последовательность значений с ключевым словом параллельно, подтипы Accum_Type и Value_Type должны статически совпадать.
Если идентификатор имя обозначения атрибута_сокращения является Parallel_Reduce, то подтипы Accum_Type и Value_Type должны статически совпадать.

Статическая семантика

Ссылка на_атрибут_сокращения обозначает значение, а его номинальный подтип — подтип первого параметра подпрограммы, обозначаемой именем редуктор_имя.

Динамическая семантика

Для вычисления последовательности значений, связи элемента_повторного_применения, указания на_блок и указания на_аспект, если таковые имеются, выполняются в произвольном порядке. Далее выполняется итерация, и для каждого значения, условно создаваемого итерацией (см. 5.5 и 5.5.2), связанное выражение вычисляется с параметром цикла, имеющим это значение, что даёт результат, преобразованный к Value_Type и используемый для определения следующего значения в последовательности.
Если последовательность значений не содержит ключевого слова параллельно, она генерируется как единая последовательность значений одним логическим потоком управления. Если ключевое слово параллельно присутствует в последовательности_значений, то окружающая ссылка на_атрибут_сокращения является параллельным конструктом, и последовательность значений генерируется параллельной итерацией (как определено в 5.5, 5.5.1 и 5.5.2), как набор непустых, неперекрывающихся смежных блоков (подпоследовательностей) с одним логическим потоком управления (см. Раздел 9) для каждой подпоследовательности. Если есть указание на_блок, оно определяет максимальное количество блоков, как определено в 5.5; в противном случае максимальное количество блоков определяется реализацией.
Для последовательности V определяется следующий атрибут:
V'Reduce(Reducer, Initial_Value)

Этот атрибут представляет выражение сокращения и имеет вид ссылки на_атрибут_сокращения.
Вычисление использования этого атрибута начинается с вычисления частей обозначения атрибута_сокращения (имя редуктора Reducer и выражение начального_значения Initial_Value) в произвольном порядке. Затем инициализируется аккумулятора выражения сокращения значением выражения начального_значения (начальное значение). После этого вычисляется последовательность V.
Если последовательность значений не содержит ключевого слова параллельно, каждое значение последовательности значений передаётся в качестве второго (Value) параметра вызова Reducer, причём первый (Accumulator) параметр — предыдущее значение аккумулятора, результат сохраняется как новое значение аккумулятора. Выражение сокращения возвращает последнее значение аккумулятора.
Если ключевое слово параллельно присутствует в последовательности значений, то выражение параллельного сокращения является параллельным конструктом, а последовательность разбивается на одну или несколько подпоследовательностей (см. выше), каждая со своим отдельным логическим потоком управления.
Каждый логический поток управления создаёт локальный аккумулятор для обработки своей подпоследовательности. Аккумулятор подпоследовательности инициализируется первым значением подпоследовательности, а вызовы Reducer начинаются со второго значения подпоследовательности (если таковое имеется). Результатом для подпоследовательности является последнее значение её локального аккумулятора.
После завершения всех логических потоков управления выражения параллельного сокращения, вызывается Reducer для каждой подпоследовательности в исходном порядке, передавая локальный накопитель для этой подпоследовательности в качестве второго (Значение) параметра, и общий накопитель (инициализированный выше начальным значением) в качестве первого (Накопитель) параметра, при этом результат сохраняется обратно в общий накопитель. Выражение параллельного сокращения возвращает конечное значение общего накопителя.
Если вычисление value_sequence возвращает пустую последовательность значений, выражение сокращения возвращает начальное значение.
Если исключение распространяется одним из вызовов Reducer, это исключение распространяется из выражения сокращения. Если разные исключения распространяются в разных логических потоках управления, одно выбирается произвольно для распространения из выражения сокращения в целом.
Для prefix X типа массива (после любого неявного разыменования) или обозначающего объект контейнера итерируемого (см. 5.5.1), определены следующие атрибуты:
X'Reduce(Reducer, Initial_Value)

X'Reduce — это выражение сокращения, которое возвращает результат, эквивалентный замене prefix атрибута на value_sequence:
[for Элемент of X => Элемент]
X'Parallel_Reduce(Reducer, Initial_Value)

X'Parallel_Reduce — это выражение сокращения, которое возвращает результат, эквивалентный замене атрибута identifier на Reduce и prefix атрибута на value_sequence:
[parallel for Элемент of X => Элемент]

Ограниченные (временные) ошибки

Для выражения параллельного сокращения это ограниченная ошибка, если подпрограмма редуктора не ассоциативна. То есть, для любых произвольных значений подтипа Value_Type A, B, C и функции редуктора R, результат R (A, R (B, C)) должен давать результат, равный R (R (A, B), C)); это ограниченная ошибка, если R этого не делает. Возможные последствия — Program_Error или результат, не соответствующий эквивалентному последовательному выражению сокращения из-за неопределённого порядка вызовов подпрограммы редуктора в общем сокращении. Аналогичные правила применяются в случае процедуры редукции.

Примеры

Пример функции выражения, которая возвращает свой результат как выражение сокращения:
function Factorial(N : Natural) return Natural is
([for J in 1..N => J]'Reduce("*", 1));
Пример выражения сокращения, которое вычисляет Синус X с помощью разложения в ряд Тейлора:
function Sine (X : Float; Num_Terms : Positive := 5) return Float is
([for I in 1..Num_Terms =>
(-1.0)**(I-1) * X**(2*I-1)/Float(Factorial(2*I-1))]
'Reduce("+", 0.0));
Пример выражения сокращения, которое выводит сумму квадратов:
Put_Line ("Сумма квадратов равна" &
Integer'Image([for I in 1 .. 10 => I**2]'Reduce("+", 0)));
Пример выражения сокращения, используемого для вычисления значения Пи:
-- См. 3.5.7.
function Pi (Number_Of_Steps : Natural := 10_000) return Real is
(1.0 / Real (Number_Of_Steps) *
[for I in 1 .. Number_Of_Steps =>
(4.0 / (1.0 + ((Real (I) - 0.5) *
(1.0 / Real (Number_Of_Steps)))**2))]
'Reduce("+", 0.0));
Пример выражения сокращения, используемого для вычисления суммы элементов массива целых чисел:
A'Reduce("+",0) -- См. 4.3.3.
Пример выражения сокращения, используемого для определения, установлены ли все элементы двумерного массива булевых значений в значение true:
Grid'Reduce("and", True) -- См. 3.6.
Пример выражения сокращения, используемого для вычисления минимального значения массива целых чисел в параллельном режиме:
A'Parallel_Reduce(Integer'Min, Integer'Last)
Пример выражения параллельного сокращения, используемого для вычисления среднего значения элементов двумерного массива подтипа Matrix (см. 3.6), которые больше 100.0:
type Accumulator is record
Sum : Real; -- См. 3.5.7.
Count : Integer;
end record;
function Accumulate (L, R : Accumulator) return Accumulator is
(Sum => L.Sum + R.Sum,
Count => L.Count + R.Count);
function Average_of_Values_Greater_Than_100 (M : Matrix) return Real is
(declare
Acc : constant Accumulator :=
[parallel for Val of M when Val > 100.0 => (Val, 1)]
'Reduce(Accumulate, (Sum => 0, Count => 0));
begin
Acc.Sum / Real(Acc.Count));


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API