ecf825b2

Функции


Синтаксис

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

Имя-функции представляет собой текстовую строку или единственный символ, которые являются константами.

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

Скобка должна следовать непосредственно за именем функции без пробелов между ними, иначе конструкция не будет распознана как вызов функции. (В этом случае предполагается наличие пустого оператора.)

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

Например, функция SUBSTR встроена в языковый процессор. Ее можно использовать следующим образом: N1='abcdefghijk' Z1='Частью N1 является: 'Substr(N1,2,7) /* присвоит Z1 строку 'Частью N1 является: bcdefgh' */

Если функция вызывается без аргументов, то после ее имени нужно указать скобки, иначе конструкция не будет распознана как вызов функции. date() /* возвращает дату в стандартном формате дд мм гггг */

Обращения к функциям и подпрограммам

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



Внутренняя     Если имя программы присутствует в процедуре в качестве метки, то сохраняется текущее состояние выполнения, так чтобы позднее можно было вернуться в точку вызова программы для продолжения выполнения процедуры. Затем управление передается первой найденной метке, которая совпадает с именем программы. Как и при вызове программы с помощью инструкции CALL, сохраняется также и некоторая другая информация состояния (назначения TRACE, NUMERIC и тому подобное). Для получения более подробной информации смотрите подраздел Инструкция CALL. Если внутренняя программа, которую нужно вызвать, является функцией, то Вы должны указать выражение в инструкции RETURN для возврата из функции. Это необязательно, если функцию вызывают в качестве подпрограммы.

Пример:

/* Рекурсивное выполнение внутренней функции... */ arg x say x'! =' factorial(x) exit

factorial: procedure /* вычисление факториала .. */ arg n /* .. рекурсивный вызов. */ if n=0 then return 1 return factorial(n-1) * n

FACTORIAL необычен тем, что он вызывает сам себя (это называется рекурсивным вызовом). Использование инструкции PROCEDURE гарантирует, что новая переменная n генерируется для каждого вызова).

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


  1. Вызов внешней программы REXX как функции аналогичен вызову внутренней программы. Однако внешняя программа является неявной ПРОЦЕДУРОЙ, в которой всегда удаляются все переменные вызывающей программы и состояние внутренних значений (назначения NUMERIC и т.д.) принимается по умолчанию (а не передаются из вызывающей программы).

  2. Другие программы REXX могут быть вызваны как функции. Вы можете использовать инструкции EXIT или RETURN для выхода из вызванной программы REXX; в любом случае нужно указать выражение.


Порядок просмотра

Порядок поиска функций аналогичен порядку их описания в этом разделе. Внутренние метки имеют наивысший приоритет, затем следуют встроенные функции, а последними идут внешние функции.

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

Пример: /* Модифицированная DATE, выдающая по умолчанию отсортированную дату */ date: procedure arg in if in='' then in='Sorted' return 'DATE'(in)

Встроенные функции имеют имена, набранные прописными буквами. Для успешного поиска встроенной функции имя в текстовой строке должно быть указано прописными буквами, как это показано в предыдущем примере. Это справедливо и для внешних функций.

Внешние функции и подпрограммы имеют системно-зависимый порядок поиска.

REXX осуществляет поиск внешних функций в следующем порядке:


  1. Функции, которые были загружены в макропространство для внеочередного выполнения
  2. Функции, являющиеся частью пакета функций
  3. Функции REXX, расположенные в текущем каталоге, с текущим расширением
  4. Функции REXX, расположенные по пути, заданному переменной среды PATH, с текущим расширением
  5. Функции REXX, расположенные в текущем каталоге, со стандартным расширением
  6. Функции REXX, расположенные по пути, заданному переменной среды PATH, со стандартным расширением
  7. Функции, которые были загружены в макропространство для выполнения в последнюю очередь.




Ошибки во время выполнения

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

Если синтаксическая ошибка происходит в процессе выполнения внешней функции, то эту ошибку можно отследить (с помощью SIGNAL ON SYNTAX) и исправить. Если ошибка не отслеживается, то выполнение программы завершается.

Возвращаемые значения

Обычно функция возвращает некоторое значение, которое подставляется на место ее вызова после вычисления выражения.

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

Программа, вызываемая как подпрограмма: Если программа возвращает некоторое значение, то оно запоминается в специальной переменной с именем RESULT. В противном случае переменная RESULT освобождается и ее значением является строка RESULT.

Программа, вызываемая как функция: Если функция возвращает некоторое значение, то оно подставляется в выражение в ту позицию, в которой ранее был указан вызов функции. В противном случае REXX прекращает обработку и выдает сообщение об ошибке.

Примеры:

/* Различные способы вызова процедуры REXX */ call Beep 500, 100 /* Пример 1: вызов подпрограммы */ bc = Beep(500, 100) /* Пример 2: вызов функции */ Beep(500, 100) /* Пример 3: результат, переданный */ /* как команда */

  • В примере 1 встроенная функция BEEP вызывается как подпрограмма REXX. Значение, возвращаемое из BEEP, помещается в специальную переменную RESULT языка REXX.

  • В примере 2 BEEP вызывается как функция REXX. Значение, возвращаемое функцией, записывается в ту позицию, в которой ранее был указан вызов функции. Предложение само по себе является оператором присваивания, поэтому значение, возвращенное после выполнения функции BEEP, помещается в переменную bc.



  • В примере 3 функция BEEP выполняется и значение, полученное после ее выполнения, подставляется в выражение для вызова функции, как в примере 2. Однако в этом случае предложение сводится к единственному выражению; поэтому вычисленное выражение передается как команда в текущую среду.


Прим.    Многие другие языки (такие как С) не используют значение, возвращаемое после выполнения функции, если оно не присвоено какой-либо переменной. Однако в языке REXX возвращаемое значение (как показано в примере 3) передается в текущую среду либо обработчику подкоманд. Если текущая среда - CMD (по умолчанию), то это действие вызовет поиск операционной системой на диске команды с указанным именем.
Встроенные функции

Язык REXX предлагает широкий выбор встроенных функций. Среди них есть функции для работы с символами, функции преобразования и информационные функции.

Ниже приведены общие замечания, касающиеся встроенных функций:


  • Указание скобок при вызове функции всегда обязательно, даже если для данной конкретной функции не нужны аргументы. Первая скобка должна следовать непосредственно за именем функции без пробела между ними.

  • Встроенные функции выполняются с внутренним назначением NUMERIC DIGITS 9 и NUMERIC FUZZ 0 и не подвержены назначениям NUMERIC, за исключением специально оговоренных случаев.

  • Вы можете указать пустую строку там, где имеется ссылка на строку.

  • Если аргумент представляет собой длину, то он должен быть неотрицательным целым числом. Если аргумент указывает начальный символ или слово в строке, то он должен быть положительным целым числом, за исключением особо оговоренных случаев.

  • Если последний аргумент необязателен, то Вы можете указать вместо него запятую, чтобы обозначить его отсутствие; например, DATATYPE(1,) и DATATYPE(1) будут выполняться совершенно аналогично.

  • Если Вы указываете символ-заполнитель, то его длина не должна превышать длину одного символа.

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

  • Преобразование между символьным и шестнадцатеричным видом влечет за собой машинное представление символьных строк, поэтому машины, работающие в кодах ASCII и EBCDIC, возвращают соответственно различные результаты.

  • Некоторые функции, описанные в этом разделе, поддерживают набор двухбайтовых символов (DBCS). Список таких функций приведен в документе Язык процедур 2/REXX для OS/2. Справочник.


    Содержание раздела