Функциональные типы
Функциональный тип — это тип, значениями которого являются методы. Функциональные типы позволяют хранить методы в переменных, передавать их в другие методы как аргументы и возвращать как результат.
Имя функционального типа содержит типы параметров и возвращаемого значения, разделенные символом лямбда-операции ->.
Например, иниц иализация и присваивание значения для функционального типа, значением которого является метод, принимающий два параметра типа Число и возвращающий значение типа Строка, может выглядеть следующим образом:
пер СуммаВСтроку: (Число, Число)->Строка = (А, Б) -> (А + Б).ВСтроку()
Значение функциональному типу может быть присвоено двумя способами:
- 
через лямбда-выражение:
пер СравнитьНаМеньше = (А: Строка, Б:Строка) -> А.Длина() < Б.Длина() - 
через ссылку на существующий метод:
пер Результат = &СуммаВСтроку 
Имя типа
Имя функционального типа содержит типы параметров и возвращаемого значения, разделенные символом лямбда-операции ->. Например:
- 
Значением типа является метод с одним параметром типа
Число, возвращающий значение типаЧисло:знч Квадрат: (Число)->Число = (Число) -> Число * Число - 
Значением типа является метод с двумя параметрами типа
Число, возвращающий значение типаБулево:знч Равенство: (Число, Число)->Булево = (А, Б) -> А == Б - 
Значением типа является метод с двумя параметрами типа
Число, возвращающий значение составного типа (СтрокаилиНеопределено):знч ДелениеВСтроку: (Число, Число)->Строка? = (А, Б) -> Б == 0 ? Неопределено : (А / Б).ВСтроку() - 
Значением типа является метод с одним параметром составного типа (
ЧислоилиНеопределено), возвращающий значение составного типа (СтрокаилиЧисло):знч КвадратИлиНеопределено: (Число?)->Строка|Число = (Ч) -> (Ч == Неопределено ? "Не определено" : Ч * Ч) - 
Значением типа является метод без параметров, возвращающий значение типа
Строка:знч Приветствие: ()->Строка = () -> "Привет, Мир!" - 
Значением типа является метод с одним параметром типа
Строка, не возвращающий ничего:знч ДобавитьВМассив: (Строка)->ничто = (Строка) -> Массив.Добавить(Строка) 
- Тип 
ничтонельзя присвоить и с ним никак нельзя взаимодействовать. - Значение типа 
(XXX)->YYYможно присвоить в переменную типа(XXX)->ничто. 
- 
Составной тип, значением которого является либо
Неопределено, либо метод с одним параметром типаЧисло, возвращающий значение типаСтрока:пер ОбработчикДоступен: Булево = Истина
// Может быть методом или Неопределено в зависимости от флага
знч ОбработчикЧисел: ((Число)->Строка)? = ОбработчикДоступен ? (Число) -> "Обработано: ${(Число * 3).ВСтроку()}" : Неопределено - 
Составной тип, значением которого является либо
Булево, либо метод с одним параметром типаЧисло, возвращающий значение типаСтрока:пер РежимАктивен = Истина
// Может быть методом или флагом типа Булево в зависимости от условий
знч ПреобразовательИлиОшибка: ((Число)->Строка)|Булево = РежимАктивен ? (Число) -> "[${Число.ВСтроку()}]" : Ложь 
Если функциональный тип входит в составной тип, то имя такого функционального типа должно быть заключено в скобки, иначе все, что следует за лямбда-операцией ->, будет считаться составным типом результата.
- 
При вызове составного функционального типа необходимо проверять его тип перед выполнением кода, чтобы избежать ошибок компиляции:
Правильнометод Преобразователь(РежимАктивен: Булево): Булево|Строка|((Число)->Строка)
знч ПреобразовательИлиОшибка: ((Число)->Строка)|Булево = РежимАктивен ? (Число) -> "[${Число.ВСтроку()}]" : Ложь
если (ПреобразовательИлиОшибка).Получ итьТип() != Тип<Булево> // Проверка типа
пер Функция = (ПреобразовательИлиОшибка как (Число)->Строка)
возврат Функция(10) // Вернет [10], если РежимАктивен = Истина
иначе
возврат ПреобразовательИлиОшибка // Вернет Ложь, если РежимАктивен = Ложь
;
;Неправильнометод Преобразователь(): Булево|Строка|((Число)->Строка)
пер РежимАктивен = Истина
знч ПреобразовательИлиОшибка: ((Число)->Строка)|Булево = РежимАктивен ? (Число) -> "[${Число.ВСтроку()}]" : Ложь
если ПреобразовательИлиОшибка это (Число)->Строка
возврат ПреобразовательИлиОшибка(10) // Функциональный вызов от свойства составного типа
иначе
возврат ПреобразовательИлиОшибка
;
; - 
Если в качестве типа переменной указано
неизвестно, то проверка типов компилятора отключается и такое значение можно вызывать с любым количеством и типом параметров. Будет ошибка или нет, станет ясно только во время выполнения кода:пер ЛюбойМетод: неизвестно
ЛюбойМетод = (Текст: Строка) -> Текст.ВВерхнийРегистр()
попытка
пер Результат1 = ЛюбойМетод("пример") // "ПРИМЕР"
поймать Иск: Исключение
// В этот блок не попадем, т. к. в ЛюбойМетод() передан корректный аргумент
;
попытка
пер Результат2 = ЛюбойМетод(42) // Ошибки компиляции нет
поймать Искл: Исключение
// Здесь будет выброшено ИсключениеПроверкиТипа
; 
В общем виде имя функционального типа выглядит следующим образом:
(тип-параметра-1, ..., тип-параметра-n)->тип-результата
Где:
- тип-параметра-1, ..., тип-параметра-N — типы параметров, если они есть;
 ->— лямбда-операция;- тип-результата — тип возвращаемого значения.
 
Вызов значения функционального типа
Синтаксически выглядит как вызов обычного метода:
[выражение.]имя([аргументы])
Например:
пер ФильтрЧисел: (Число)->Булево = (Ч) -> Ч > 0     // Инициализация
пер Результат = ФильтрЧисел(-5)                     // Вызов
пер ФорматироватьДату: (Дата)->Строка = (Д) -> Д.Представление("dd.MM.yyyy")    // Инициализация
пер Результат = ФорматироватьДату(Дата.Сейчас())                                // Вызов
При этом действует следующий приоритет разрешения имен:
- если существует метод с указанным именем (любого приоритета), то считается, что это вызов метода;
 - иначе ищется свойство с указанным именем в порядке приоритетов и считается вызовом функционального типа.
 
Иерархия типов и вариантность
Значения функциональных типов обеспечивают ковариантность по возвращаемым типам и контравариантность по типам параметров.