Лямбдас это библиотека для реализации функциональных интерфейсов в ваших библиотеках
Поддерживаются следующие варианты синтаксиса лямбда выражений:
// 1
"(ПараметрПервый, ПараметрВторой, ПараметрТретий) -> { Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий }"
// 2
"(ПараметрПервый, ПараметрВторой, ПараметрТретий) -> Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий"
// 3
"ПараметрПервый, ПараметрВторой, ПараметрТретий -> { Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий }"
// 4
"ПараметрПервый, ПараметрВторой, ПараметрТретий -> Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий"
Допустим, у вас есть библиотека, в рамках которой вы хотите позволить потребителю удалять элементы из массива по некоторому условию.
Вы добавляете метод:
// МояКласснаяБиблиотека.os
Процедура УдалитьПоУсловию(Условие) Экспорт
Действие = Лямбда.Выражение(Условие)
.ВДействие();
Для каждого Элемент из Коллекция Цикл
Если Действие.Выполнить() Тогда
Коллекция.Удалить(Элемент);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В данном примере вы получаете Действие на метод который был создан по переданному выражению, и вызов вашего метода теперь может выглядеть вот так:
// ПотребительМоейКласснойБиблиотеки.os
Процедура Удалить()
// Удалим из коллекции все элементы которые больше или равны двум
МояКласснаяБиблиотека.УдалитьПоУсловию("Элемент -> Возврат Элемент >= 2");
КонецПроцедуры
Для лямбда выражения можно указать функциональный интерфейс который она будет реализовывать, эта возможность преследует две цели
- Проверить что переданное выражение соответствует вашим ожиданиям, Функция это или Процедура, и количество параметров
- Предоставить возможность не писать возврат в однострочных лямбда выражениях вашим потребителям, если это функция
В составе библиотеки поставляет ряд функциональных интерфейсов (в модуле ФункциональныеИнтерфейсы
):
- УниФункция - Функция
Применить
с одним параметром - БиФункция - Функция
Применить
с двумя параметром - ТерФункция - Функция
Применить
с тремя параметром - УниПроцедура - Процедура
Принять
с одним параметром - БиПроцедура - Процедура
Принять
с двумя параметрами - ТерПроцедура - Процедура
Принять
с тремя параметрами
Так же можно установить произвольный ИнтерфейсОбъекта
для создания метода по нему
Если интерфейс не был передан явно, то будет предпринята попытка автоматически подобрать один из интерфейсов из списка выше, в зависимости от количества параметров лямбда выражения и наличия возврата значения в его тексте
Например:
// МояКласснаяБиблиотека.os
Процедура Сортировать(СравнениеЗначений) Экспорт
Интерфейс = Новый ИнтерфейсОбъекта();
Интерфейс.ФункцияИнтерфейса("Сравнить", 2);
Компаратор = Лямбда.Выражение(СравнениеЗначений)
.Интерфейс(Интерфейс)
.ВОбъект();
Для каждого Элемент Из Коллекция Цикл
РезультатСравнения = Компаратор.Сравнить(Элемент, СледующийЭлемент);
Если РезультатСравнения > 0 Тогда
// ...
ИначеЕсли РезультатСравнения < 0 Тогда
// ...
Иначе
// ...
КонецЕсли;
// Алгоритм сортировки
КонецЦикла;
КонецПроцедуры
Тут мы использовали метод ВОбъект
для получения сценария который реализует наш переданный интерфейс, и обратились по имени метода который мы отразили в интерфейсе.
Вызов метода:
// ПотребительМоейКласснойБиблиотеки.os
МояКласснаяБиблиотека.Сортировать("Первый, Второй ->
| Если Первый > Второй Тогда
| Возврат 1;
| ИначеЕсли Второй > Первый Тогда
| Возврат -1;
| Иначе
| Возврат 0;
| КонецЕсли;"
);
Пример необязательного возврата:
// МояКласснаяБиблиотека.os
Процедура Заменить(Массив, Выражение) Экспорт
Действие = Лямбда.Выражение(Выражение)
.Интерфейс(ФункциональныеИнтерфейсы.УниФункция())
.ВДействие();
Счетчик = 0;
Для Счетчик = 0 По Массив.ВГраница() Цикл
Массив.Установить(Счетчик, Действие.Выполнить(Массив[Счетчик]));
КонецЦикла;
КонецПроцедуры
// ПотребительМоейКласснойБиблиотеки.os
Массив = Новый Массив();
Массив.Добавить(1);
Массив.Добавить(2);
Массив.Добавить(3);
Заменить(Массив, "Элемент -> Элемент + 1");
Сообщить(Массив[0]);
Сообщить(Массив[1]);
Сообщить(Массив[2]);
// > 2
// > 3
// > 4
Лямбда выражению можно установить Контекст
это позволить использовать поля контекста прямо в выражении, контекстом может выступать только структура
Например:
// МояКласснаяБиблиотека.os
Процедура СделайДело(ЧтоСделать) Экспорт
ДелоПервое = Новый Структура("Состояние", "НеСделано");
ДелоВторое = Новый Структура("Состояние", "НеСделано");
Контекст = Новый Структура(
"ДелоПервое, ДелоВторое",
ДелоПервое,
ДелоВторое
);
Делатель = Лямбда.Выражение(ЧтоСделать)
.Контекст(Контекст)
.ВДействие();
Делатель.Выполнить(1);
Сообщить("ДелоПервое = " + ДелоПервое.Состояние);
Сообщить("ДелоВторое = " + ДелоВторое.Состояние);
КонецПроцедуры
Вызов метода:
// ПотребительМоейКласснойБиблиотеки.os
МояКласснаяБиблиотека.СделайДело("(НомерДела) ->
| Если НомерДела = 1 Тогда
| ДелоПервое.Состояние = ""Сделано""
| ИначеЕсли НомерДела = 2 Тогда
| ДелоВторое.Состояние = ""Сделано""
| КонецЕсли;"
);
Результат:
ДелоПервое = Сделано
ДелоВторое = НеСделано
Как мы видим поля контекста доступны в лямбда выражении по именам ключей структуры контекста
В лямбда выражение можно захватить какой-то объект, для того что бы в тексте лямбда выражения можно было использовать публичные и приватные поля объекта, а так же публичные методы
Например:
// МояКласснаяБиблиотека.os
Функция Единичка(Алгоритм, Объект) Экспорт
Действие = Лямбда.Выражение(Алгоритм)
.ЗахватитьОбъект(Объект)
.ВДействие();
Возврат Действие.Выполнить(1);
КонецФункции
Вызов метода:
// ПотребительМоейКласснойБиблиотеки.os
Перем Двойка;
Перем Тройка Экспорт;
Функция Четверка() Экспорт
Возврат 4;
КонецФункции
Результат = МояКласснаяБиблиотека.Единичка(
"(Единица) -> Возврат Единица + Двойка + Тройка + Четверка()",
ЭтотОбъект
);
// Результат = 10
Как мы видим в выражении возможно обратится к полям и методам переданного объекта
// Создаёт лямбда выражение из переданного выражения
//
// Параметры:
// Выражение - Строка - Выражение из которого будет создано лямбда выражение
//
// Возвращаемое значение:
// ЛямбдаВыражение - Созданное лямбда выражение
//
Функция Выражение(Выражение)
Процедура ПриСозданииОбъекта(Выражение)
// Устанавливает функциональный интерфейс для лямбда выражения.
// В случае если метод интерфейса это функция:
// 1. Добавляет "Возврат" в лямбда выражение если оно однострочное и не содержит возврат
// 2. Проверяет что многострочное выражение содержит возврат значения
// В случае В случае если метод интерфейса это процедура:
// 1. Проверяет что выражение не содержит возврат значения
//
// Параметры:
// Интерфейс - ИнтерфейсОбъекта - Устанавливаемый функциональный интерфейс
//
// Возвращаемое значение:
// ЛямбдаВыражение - Инстанс текущего выражения
//
Функция Интерфейс(Интерфейс)
// Устанавливает контекст для лямбда выражения.
// При исполнении лямбда выражения все значения контекста будут доступны для использования в лямбда выражении
//
// Параметры:
// Контекст - Структура - Устанавливаемый контекст
//
// Возвращаемое значение:
// ЛямбдаВыражение - Инстанс текущего выражения
//
Функция Контекст(Контекст)
// Захватывает переданный объект для использования его в качестве контекста лямбда выражения.
// При исполнении лямбда выражения в нём будут доступны публичные и приватные поля переданного объекта
// а так же публичные методы.
//
// Параметры:
// Объект - Сценарий - Захватываемый объект
//
// Возвращаемое значение:
// ЛямбдаВыражение - Инстанс текущего выражения
//
Функция ЗахватитьОбъект(Объект)
// Возвращает действие (делегат) на метод созданный по лямбда выражению
//
// Возвращаемое значение:
// Действие - Действие на метод лямбда выражения
//
Функция ВДействие()
// Возвращает сценарий созданный по лямбда выражению, который содержит метод согласно интерфейса
//
// Возвращаемое значение:
// Сценарий - Созданный сценарий
//
Функция ВОбъект()
// Возвращает интерфейс объекта содержащий функцию с одним параметром
//
// Возвращаемое значение:
// ИнтерфейсОбъекта - Искомый интерфейс
//
Функция УниФункция()
// Возвращает интерфейс объекта содержащий функцию с двумя параметрами
//
// Возвращаемое значение:
// ИнтерфейсОбъекта - Искомый интерфейс
//
Функция БиФункция()
// Возвращает интерфейс объекта содержащий функцию с тремя параметрами
//
// Возвращаемое значение:
// ИнтерфейсОбъекта - Искомый интерфейс
//
Функция ТерФункция()
// Возвращает интерфейс объекта содержащий процедуру с одним параметром
//
// Возвращаемое значение:
// ИнтерфейсОбъекта - Искомый интерфейс
//
Функция УниПроцедура()
// Возвращает интерфейс объекта содержащий процедуру с двумя параметрами
//
// Возвращаемое значение:
// ИнтерфейсОбъекта - Искомый интерфейс
//
Функция БиПроцедура()
// Возвращает интерфейс объекта содержащий процедуру с тремя параметрами
//
// Возвращаемое значение:
// ИнтерфейсОбъекта - Искомый интерфейс
//
Функция ТерПроцедура()