11 · Процедуры и функции
Вызовы
Объявленная подпрограмма начинает работать только тогда, когда её вызывают с конкретными аргументами. Одна и та же форма вызова обслуживает процедуру, функцию, функциональное значение и метод записи; различаются они тем, что объявлено под именем, и тем, используется ли результат.
Формы вызова
Вызов записывается именем с аргументами в скобках, функциональным значением или именем метода у записи. Аргументы — выражения через запятую в порядке параметров; даже пустой вызов требует скобок.
<имя>(⟦<аргументы>⟧)<функциональное значение>(⟦<аргументы>⟧)<запись>.<метод>(⟦<аргументы>⟧)Имя обозначает объявленную подпрограмму или встроенную функцию. Функциональное значение имеет тип FUNCTION с подходящими параметрами и результатом. Запись является значением пользовательского TYPE, метод объявлен внутри этого типа.
Вызов допустим на верхнем уровне и в теле подпрограммы. SUB выполняется отдельной инструкцией; FUNCTION может участвовать в выражении или выполняться отдельной инструкцией с отброшенным результатом. Метод вызывает тело объявления внутри TYPE для указанной записи.
Передача аргументов
Квадратные скобки массива не заменяют круглые скобки вызова: ShowBasket(fruits[]) передаёт весь массив, а ShowFruit(fruits[2]) — один элемент. Если функция возвращает массив, MakeFruits()[2] сначала вызывает её, затем читает элемент результата. Именованный массивный параметр объявляется как values[] AS STRING; безымянный массивный тип в сигнатуре — как STRING[].
Список параметров содержит объявления через запятую. Каждый параметр задаёт имя и тип после AS; пустой список допустим. Список аргументов содержит выражения в том же порядке. Тип аргумента должен совпадать с типом параметра либо допускать предусмотренное языком преобразование.
BYVAL применяется по умолчанию и передаёт независимую копию значения. Это правило действует для чисел, строк, массивов, TYPE, DICTIONARY и HASHSET. Вложенные изменяемые данные также копируются: изменение элемента массива или коллекции внутри параметра не меняет данные вызывающего кода. Аргумент фиксируется сразу после своего вычисления, до вычисления следующих аргументов. BYREF, напротив, явно связывает параметр с исходной переменной; изменение через такой параметр видно вызывающему коду. Функциональные значения с захватами и внешние ресурсы этим правилом автоматически не дублируются.
BYREF связывает параметр с переменной; массивная переменная записывается с обязательным суффиксом []. Тип должен точно совпадать; преобразование аргумента не допускается. Поле записи, элемент массива и вычисляемое выражение не являются допустимым аргументом BYREF. Передача CONST через BYREF отвергается диагностикой MB2010; для изменяемого аргумента используйте обычную переменную DIM. Неявный получатель метода TYPE подчиняется отдельному правилу: SELF связан с фактическим полем или элементом массива, поэтому вызов метода у составного получателя изменяет именно этот экземпляр, а не временную копию. Подробности приведены в разделе о методах TYPE.
Именованные аргументы Field := value поддерживаются только в именованном литерале TYPE; обычные подпрограммы и встроенные функции принимают позиционные аргументы. Все формы встроенных функций перечислены в каталоге функций.
Вызов через функциональное значение
Если функция сохранена в переменной, вызов идёт через неё, а не через исходное имя:
FUNCTION Square(value AS INTEGER) AS INTEGER
RETURN value * value
END FUNCTION
DIM operation AS FUNCTION(INTEGER) AS INTEGER
operation = Square
PRINT operation(4)Программа выводит:
16Переменная operation хранит функциональное значение с той же сигнатурой, что и Square, поэтому аргумент 4 передаётся в исходное тело функции, а результат возвращается в выражение PRINT.
Изменение копии и оригинала
В первой процедуре BYVAL защищает исходный массив от изменения. Во второй BYREF явно разрешает изменить переданную переменную.
DIM prices[] AS INTEGER = [10]
ChangeCopy(prices[])
PRINT prices[1]
ChangeOriginal(prices[])
PRINT prices[1]
SUB ChangeCopy(BYVAL values[] AS INTEGER)
values[1] = 20
END SUB
SUB ChangeOriginal(BYREF values[] AS INTEGER)
values[1] = 30
END SUBВывод:
10
30Запускаемая программа. Для вложенных данных действует то же правило: покупка с товарами и пометками.
Диагностика
MB2004 означает неверное число аргументов; MB2003 — несовместимый тип; MB2005 — неизвестное вызываемое имя. MB2028 возникает для недопустимого аргумента BYREF. Повторное имя в одной области даёт MB2002; запрещённое перекрытие внешнего имени — MB2016. Избыточная рекурсия даёт MB3011 во время выполнения.
MB2020 означает, что значение нельзя вызвать; MB2019 — использование SUB как значения. MB2040 запрещает отдельную инструкцию из выражения без вызова. MB3009 возникает при вызове пустого функционального значения.
См. также
Кортежи
Связанные значения разных типов можно хранить в кортеже, объявлять с полным или общим типом группы, передавать функции и распаковывать. Все формы и примеры приведены на странице кортежей.