next up previous contents
След.: Автоматические и перенимающие массивы Выше: Процедуры Пред.: Процедуры   Содержание


Объявление и определение процедур

Процедуры -- это самостоятельные программные единицы, вызываемые из основной программы или других процедур. Могут получать параметры (иначе именуемые аргументами) и определять их значения. В современном Фортране введены (необязательные) атрибуты параметров, описывающие их как входящие (в том числе константы), которые не могут быть изменены в процедуре, исходящие, исходные значения которых в процедуре не используются, а заменяются другими, и смешанные, значение которых используется и заменяется другим. По умолчанию назначается смешанный атрибут.

Процедуры делятся на подпрограммы и функции; первые вызываются оператором CALL, вторые возвращают значение определенного типа и могут быть операндами в выражениях. В стандарте описан ряд подпрограмм и функций, а также они могут создаваться программистом.

Процедуры могут быть внешними, внутренними и модульными. Внешние процедуры описываются в отдельных файлах. Модульные -- в модулях. Внутренние процедуры содержатся в основной программе или других процедурах (внутренние процедуры не могут иметь свои внутренние процедуры) и отделяются от тела оператором CONTAINS. После описания внутренних процедур идет оператор END, завершающее программу или процедуру. Аналогично описываются и модульные процедуры.

Внешние процедуры можно снабдить атрибутом EXTERNAL (например, в одноименном операторе, операторе PROCEDURE или интерфейсном блоке). Это означает, что она внешняя, что позволяет избежать двусмысленности, если существует встроенная одноименная процедура (что немаловажно для переносимости). Если процедура используется как фактический аргумент другой процедуры, она должна иметь этот атрибут.

Процедура может иметь атрибут INTRINSIC, означающий, что она встроенная. Если встроенная процедура используется как фактический параметр процедуры, она должна иметь этот атрибут.

Общий вид подпрограммы:

[префикс]SUBROUTINE имя [([параметры])]

объявление данных

операторы

END [SUBROUTINE [имя]]

Общий вид функции:

[префикс]FUNCTION имя ([параметры]) [RESULT(имя)]

объявление данных

операторы

END [FUNCTION [имя]]

Префикс может содержать тип (для функций) и ряд атрибутов:

PURE -- атрибут «стерильной» процедуры, то есть процедуры без побочного эффекта в терминологии [2]. Стерильная процедура не может менять ничего вне своего тела: она не осуществляет ввод и вывод, не меняет значения переменных, определенных вне ее тела, если даже имеет к ним доступ, не завершает программу и т.д. Стерильность процедур -- один из признаков функционального программирования. Побочный эффект может чрезвычайно осложнить параллелизацию программы, поэтому возможность его запрета весьма важна. Аргументы стерильных функций обязаны иметь атрибут INTENT(IN), то есть функция не может менять значения своих аргументов. Аргументы стерильных подпрограмм должны иметь атрибут INTENT, но не обязательно INTENT(IN), то есть подпрограмма может возвращать результаты через свои аргументы. Атрибут SAVE в стерильных процедурах не допускается; инициализация также не допускается, так как она неявно назначает атрибут SAVE. В Стандарте имеется указание, что если в выражении имеется вызов более, чем одной функции, они могут вычисляться в любом порядке, в том числе -- параллельно, и результаты не должны зависеть от порядка вычислений. Поэтому компилятор вправе запретить выражение $ \texttt{F(X)+G(X)}$ , если одна или обе функции изменяют аргумент, а выражение X*G(X) может не совпадать с G(X)*X.

ELEMENTAL -- атрибут поэлементной процедуры, то есть процедуры со скалярными параметрами (и скалярным значением функции), которую можно вызвать с аргументами-массивами одинаковой конфигурации и она проведет вычисления поэлементно. Если это функция, то она должна возвращать скалярное значение, а будучи вызванной с аргументами-массивами, возвращает массив той же конфигурации. Поэлементная процедура всегда стерильна, если не указан атрибут IMPURE.

RECURSIVE -- атрибут рекурсивной процедуры, то есть процедуры, которая может вызывать себя, прямо или косвенно. Не может быть поэлементной, но может быть стерильной. Для результата функции должно быть указано имя, так как имя рекурсивной функции означает ее саму, а не ее результат, в отличие от нерекурсивной.

Атрибут MODULE определяет специальную модульную процедуру (процедуры, описанные в модулях, доступны и без этого атрибута, он подчеркивает, что процедура модульная и требует явного интерфейса).

Тип и атрибуты функции (и атрибуты подпрограммы) можно задать в ее теле в разделе объявлений. Если тип функции не указан, он определяется неявно. Имя результата (для функций) может быть определено с помощью ключевого слова RESULT и не должно совпадать с именем функции; имя результата по умолчанию совпадает с именем функции. Для рекурсивных функций имя результата должно быть задано.

Список параметров, если они есть, состоит из имен формальных аргументов, разделенных запятыми. Формальные имена используются в теле процедуры. Имена фактических параметров не обязаны совпадать с формальными. Формальные имена могут служить ключами (см. ниже). В процедуре следует объявить параметры: тип (если он не определяется неявно) и атрибуты. Помимо общих атрибутов, аргументы процедур могут иметь ряд специфических атрибутов:

INTENT -- атрибут входящих и исходящих данных. Параметры процедуры с атрибутом INTENT(IN) являются входящими и не могут изменяться в процедуре. Исходящие параметры имеют атрибут INTENT(OUT) -- они получают значение в процедуре, а их исходное значение не играет роли (более того, оно становится неопределенным). Наконец, INTENT(INOUT) допускает использование значения в процедуре и присвоение нового значения. Применение атрибутов не обязательно, но желательно, поскольку существенно облегчает работу оптимизатору, а также позволяет контролировать вычисления (традиционная для Фортрана схема возврата результатов расчетов в параметрах процедур довольно сложна для сопровождения, особенно чужого кода). Если формальный аргумент -- указатель, атрибут относится к статусу связанности, а не значению связанного с ним объекта.

VALUE -- атрибут параметра, переданного по значению. Если в качестве параметра передается переменная, она передается по ссылке; в частности, изменения (если это не входящий параметр) значения этого параметра в процедуре отражаются на переменной, переданной в качестве параметра. Атрибут VALUE дает возможность передать параметр по значению: изменения параметра в процедуре допустимы, но на переменной, переданной в качестве параметра, не отражаются.

OPTIONAL -- атрибут необязательного параметра процедуры. Аргумент с таким атрибутом может быть опущен при вызове. Проверить его наличие позволяет стандартная функция PRESENT(A), принимающая имя формального необязательного параметра. Неразмещенный массив и несвязанный указатель в качестве необязательного параметра расцениваются как отсутствующий параметр.

При вызове функций без параметров пустые круглые скобки обязательны, для подпрограмм они не обязательны. Параметры процедур могут быть позиционными (соответствие фактического аргумента формальному, указанному при описании процедуры, осуществляется по его номеру в списке) и ключевыми, когда прямо указано соответствие фактического аргумента формальному. Например:

SUBROUTINE SUB(A,B,C,D)

...

END SUBROUTINE

...

CALL SUB(1, 2, D=3, C=4)

При указании аргументов в ключевой форме порядок не играет роли.

Необязательные аргументы, если они есть (с атрибутом OPTIONAL) могут быть опущены при вызове; однако если необязательный аргумент опущен, то либо все аргументы после него -- необязательные и опущены, либо указаны в ключевой форме.

Выход из процедуры осуществляется оператором RETURN. Параметров он не имеет (форма с параметром признана устаревшей и ее описание опускаем). Если оператор RETURN отсутствует процедура завершается по достижении слова END.

Функция может возвращать строку, массив или указатель.



Ilya A. Chernov 2012-12-19
X