Каталог решений - Лямбда-функции на встроенном языке 1С

Лямбда-функции на встроенном языке 1С

Лямбда-функции на встроенном языке 1С

В наличии

Анонимная функция средствами 1С. Пророчества грядущих функций первого класса и ООП. Другие смелые заявления.

Категория:

Описание

«Анонимные функции, функции как переменные, методы для структур и соответствий, классы/прототипы, наследование! Где это всё?!» — спросите вы меня. И я уверенно отвечу: «Здесь». В этой теме ключ ко всему. Решение небольшое, элегантное, исключительно на встроенном языке 1С и как прививка от коронавируса: молодое, обнадеживающее, многообещающее, но еще не протестированное на массах. Поэтому прошу пока воспринимать всё, как альфа-версию, или даже, как концепцию. Кстати, под словом "Функция" здесь и ниже понимаются и процедуры тоже. 

Имея опыт программирования на Python и JavaScript, страдаю, когда в 1С функция не может быть объектом первого класса. То есть, функцию нельзя поместить в переменную. Не результат выполнения функции, а саму функцию. Это лишает возможности передавать её, как параметр, в другие функции или программно создавать объекты c методами. Мы не можем ждать милости от 1С, и добавим нужные механизмы сами!

 

Материал будет разбит на несколько публикаций. Сегодня рассмотрим основу всей затеи — анонимную функцию.

Анонимные функции

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

  //Каждое четное число в массиве умножить на 3
  ForEach(Массив, "Если _1 % 2 = 0 Тогда Возврат _1 * 3; КонецЕсли;");
  
  //Отобрать элементы, состоящие из заглавных букв:
  НовыйМассив = Filter(Массив, "Возврат _1 = ВРЕГ(_1);");

ForEach и Filter — обычные функции. Как именно они написаны, покажу ниже. Сейчас важно отметить, что они обрабатывают массив с помощью анонимных функций (второй параметр). Это, во-первых, позволяет сократить код без потери читаемости, и, во-вторых, хранить и передавать тело анонимной функции куда нужно.

 

Пару дней назад я захотел в режиме предприятия написать произвольный код в поле ввода, нажать на кнопку, и чтобы этот код выполнился над списком отобранных объектов. Должен признаться, иногда я тайком использую команды Выполнить/Вычислить и в этот раз на них рассчитывал. Каково же было мое изумление, когда узнал, что эти конструкции не понимают таких важных вещей как: Возврат, Процедура, Функция! Тогда я создал функцию Lambda, которая умеет выполнять код с возвратами.

Lambda(Код, [Аргументы: _1, _2, … _n])

Суть такова. В эту функцию подается код в виде строки и аргументы по необходимости. К аргументам можно обращаться по номерам с подчеркиванием (например, _1). К сожалению, из-за особенности языка 1С максимальное количество аргументов определено заранее (в данных примерах — максимум 4). Все возвраты перед выполнением заменяются на конструкцию с использованием б-гомерзких (да будут они преданы забвению) операторов goto. Таким образом, результат возврата помещается в служебную переменную (ProgmaLambdaResult) и тут же осуществляется переход к концу функции Lambda, где происходит обычный возврат результата. В тексте переданного кода для повышения читаемости допускается заменять две двойные кавычки на символ ` (на клавиатуре, где Ё). Код считается "скомпилированным", если первый символ #.

  //Пример использования:
  // Lambda вызывается с тремя параметрами:
  //   Код,
  //   _1 = СписокОбъектов
  //   _2 = "Слава Тьюрингу!"
  // Результат (Истина или Ложь) вернется в переменную ЕстьПрославлениеТьюринга 
  //
  ЕстьПрославлениеТьюринга = Lambda("
      |СтрокаПоиска = ВРЕГ(_2);
      |Для каждого Значение из _1 Цикл
      |   Если Найти(ВРЕГ(Значение.Наименование), СтрокаПоиска) <> 0 Тогда
      |       Возврат Истина;
      |   КонецЕсли;
      |КонецЦикла;
      |Возврат Ложь;
      |", СписокОбъектов, "Слава Тьюрингу!"
  );

Вот так это сейчас реализовано:

 

has been added to your cart:
Оформление заказа