artbear / lambdas

API для реализации функциональных интерфейсов для OneScript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

lambdas

Лямбдас это библиотека для реализации функциональных интерфейсов в ваших библиотеках

How to

Синтаксис лямбда выражения:

Поддерживаются следующие варианты синтаксиса лямбда выражений:

// 1
"(ПараметрПервый, ПараметрВторой, ПараметрТретий) -> { Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий }"

// 2
"(ПараметрПервый, ПараметрВторой, ПараметрТретий) ->  Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий"

// 3
"ПараметрПервый, ПараметрВторой, ПараметрТретий -> { Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий }"

// 4
"ПараметрПервый, ПараметрВторой, ПараметрТретий -> Возврат ПараметрПервый + ПараметрВторой + ПараметрТретий"

Простой пример

Допустим, у вас есть библиотека, в рамках которой вы хотите позволить потребителю удалять элементы из массива по некоторому условию.

Вы добавляете метод:

// МояКласснаяБиблиотека.os

Процедура УдалитьПоУсловию(Условие) Экспорт

    Действие = Лямбда.Выражение(Условие)
        .ВДействие();

    Для каждого Элемент из Коллекция Цикл

        Если Действие.Выполнить() Тогда
            Коллекция.Удалить(Элемент);
        КонецЕсли;

    КонецЦикла;

КонецПроцедуры

В данном примере вы получаете Действие на метод который был создан по переданному выражению, и вызов вашего метода теперь может выглядеть вот так:

// ПотребительМоейКласснойБиблиотеки.os

Процедура Удалить()

    // Удалим из коллекции все элементы которые больше или равны двум
    МояКласснаяБиблиотека.УдалитьПоУсловию("Элемент -> Возврат Элемент >= 2");

КонецПроцедуры

Интерфейсы

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

  1. Проверить что переданное выражение соответствует вашим ожиданиям, Функция это или Процедура, и количество параметров
  2. Предоставить возможность не писать возврат в однострочных лямбда выражениях вашим потребителям, если это функция

В составе библиотеки поставляет ряд функциональных интерфейсов (в модуле ФункциональныеИнтерфейсы):

  1. УниФункция - Функция Применить с одним параметром
  2. БиФункция - Функция Применить с двумя параметром
  3. ТерФункция - Функция Применить с тремя параметром
  4. УниПроцедура - Процедура Принять с одним параметром
  5. БиПроцедура - Процедура Принять с двумя параметрами
  6. ТерПроцедура - Процедура Принять с тремя параметрами

Так же можно установить произвольный ИнтерфейсОбъекта для создания метода по нему

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

Например:

// МояКласснаяБиблиотека.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. Проверяет что выражение не содержит возврат значения
//
// Параметры:
//   Интерфейс - ИнтерфейсОбъекта - Устанавливаемый функциональный интерфейс
//
//  Возвращаемое значение:
//   ЛямбдаВыражение - Инстанс текущего выражения
//
Функция Интерфейс(Интерфейс) 

Контекст

// Устанавливает контекст для лямбда выражения.
// При исполнении лямбда выражения все значения контекста будут доступны для использования в лямбда выражении
//
// Параметры:
//   Контекст - Структура - Устанавливаемый контекст
//
//  Возвращаемое значение:
//   ЛямбдаВыражение - Инстанс текущего выражения
//
Функция Контекст(Контекст) 

ЗахватитьОбъект

// Захватывает переданный объект для использования его в качестве контекста лямбда выражения.
// При исполнении лямбда выражения в нём будут доступны публичные и приватные поля переданного объекта
//  а так же публичные методы.
//
// Параметры:
//   Объект - Сценарий - Захватываемый объект
//
//  Возвращаемое значение:
//   ЛямбдаВыражение - Инстанс текущего выражения
//
Функция ЗахватитьОбъект(Объект) 

ВДействие

// Возвращает действие (делегат) на метод созданный по лямбда выражению
//
//  Возвращаемое значение:
//   Действие - Действие на метод лямбда выражения
//
Функция ВДействие() 

ВОбъект

// Возвращает сценарий созданный по лямбда выражению, который содержит метод согласно интерфейса
//
//  Возвращаемое значение:
//   Сценарий - Созданный сценарий
//
Функция ВОбъект() 

ФункциональныеИнтерфейсы

УниФункция

// Возвращает интерфейс объекта содержащий функцию с одним параметром
//
//  Возвращаемое значение:
//   ИнтерфейсОбъекта - Искомый интерфейс
//
Функция УниФункция() 

БиФункция

// Возвращает интерфейс объекта содержащий функцию с двумя параметрами
//
//  Возвращаемое значение:
//   ИнтерфейсОбъекта - Искомый интерфейс
//
Функция БиФункция() 

ТерФункция

// Возвращает интерфейс объекта содержащий функцию с тремя параметрами
//
//  Возвращаемое значение:
//   ИнтерфейсОбъекта - Искомый интерфейс
//
Функция ТерФункция() 

УниПроцедура

// Возвращает интерфейс объекта содержащий процедуру с одним параметром
//
//  Возвращаемое значение:
//   ИнтерфейсОбъекта - Искомый интерфейс
//
Функция УниПроцедура() 

БиПроцедура

// Возвращает интерфейс объекта содержащий процедуру с двумя параметрами
//
//  Возвращаемое значение:
//   ИнтерфейсОбъекта - Искомый интерфейс
//
Функция БиПроцедура() 

ТерПроцедура

// Возвращает интерфейс объекта содержащий процедуру с тремя параметрами
//
//  Возвращаемое значение:
//   ИнтерфейсОбъекта - Искомый интерфейс
//
Функция ТерПроцедура() 

About

API для реализации функциональных интерфейсов для OneScript

License:MIT License


Languages

Language:1C Enterprise 100.0%