«Анонимные функции, функции как переменные, методы для структур и соответствий, классы/прототипы, наследование! Где это всё для 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 Тогда
| Возврат Истина;
| КонецЕсли;
|КонецЦикла;
|Возврат Ложь;
|", СписокОбъектов, "Слава Тьюрингу!"
);
Вот так это сейчас реализовано:
//Функция возвращает результат выполнения Кода. Нумерованные параметры можно использовать для передачи произвольных значений,
// необходимых для выполнени кода. Возвращает Null по умолчанию.
//
// !!! Команда "Возврат" всегда должна писаться с заглавной буквы и закрываться ";" (точкой с запятой)
// !!! В Коде не должно быть команд: Функция, Процедура и их концов. Только тело.
//
//Параметры:
// Код - Строка - тело процедуры или функции
// _1 - произвольное значение (то же самое для _2, _3 ... _n)
//
Функция Lambda(знач Код, _1=Неопределено, _2=Неопределено, _3=Неопределено, _4=Неопределено)
ProgmaLambdaResult = null; // переменная, в которую вернется результат функции (если нужно)
// Код, начинающийся с символа # считается уже скомпилированным
Выполнить ?(Лев(Код, 1) = "#", Сред(Код, 2), CompileCode(Код));
~ProgmaLambdaReturn: // метка, к которой переходит алгоритм при возвратах
Возврат ProgmaLambdaResult;
КонецФункции
//Функция подготавливает код для выполнения в Lambda()
//
//Параметры:
// Код - Строка - код на языке 1С.
// Допускается для обозначений строк внутри кода вместо "" использовать ` (где ё).
// Код, начинающийся с # считается уже скомпилированным.
// Команда "Возврат" всегда должна писаться с заглавной буквы и закрываться ";" (точкой с запятой).
// Все Возвраты вне строк заменяются на специальные метки, необходимые для функции Lambda().
// В Коде не должно быть команд: Функция, Процедура и их концов. Только тело.
//
Функция CompileCode(знач Код)
Если Лев(Код, 1) = "#" Тогда
Возврат Код;
КонецЕсли;
Код = toCode(Код);
_Возврат = "Возврат";
ДлинаСловаВозврат = СтрДлина(_Возврат);
ПозицияВозврата = FindWithinCode(Код, _Возврат);
Пока ПозицияВозврата <> 0 Цикл
КодДо = Лев(Код, ПозицияВозврата-1);
КодПосле = Сред(Код, ПозицияВозврата + ДлинаСловаВозврат);
КонецКоманды = FindWithinCode(КодПосле, ";");
ЗначениеВозврата = Лев(КодПосле, КонецКоманды-1);
Если ПустаяСтрока(ЗначениеВозврата) Тогда // Процедуры
Код = КодДо + "Перейти ~ProgmaLambdaReturn" + КодПосле;
Иначе // Функции
Код = КодДо + "ProgmaLambdaResult =" + ЗначениеВозврата
+ "; Перейти ~ProgmaLambdaReturn;" + Сред(КодПосле, КонецКоманды+1);
КонецЕсли;
ПозицияВозврата = FindWithinCode(Код, _Возврат);
КонецЦикла;
Возврат Код;
КонецФункции
//Функция переводит Значение в вид, необходимый для выполнения в Lambda()
//
//Параметры:
// Значение - произвольное значение
//
Функция toCode(знач Значение)
Если Значение = Неопределено Тогда
Возврат "Неопределено";
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Строка") Тогда
// Декодирование синтаксического сахара
Возврат СтрЗаменить(СокрЛП(Значение), "`", """");
КонецЕсли;
Возврат Значение;
КонецФункции
//Аналог функции Найти, только игнорирует текст внутри кавычек "" и комментарии.
//
//Параметры:
// Стр - Строка - Строка, в которой проводится поиск
// Подстрока - Строка - Строка, которую нужно найти
//
Функция FindWithinCode(Стр, Подстрока)
Накопитель = "";
ДлинаНакопителя = 0;
ДлинаПодстроки = СтрДлина(Подстрока);
ВнутриКавычек = Ложь;
ВнутриКомментрия = Ложь;
Для i = 1 по СтрДлина(Стр) Цикл
Символ = Сред(Стр, i, 1);
Если ВнутриКомментрия Тогда
Если Символ = Символы.ПС или Символ = Символы.ВК Тогда
ВнутриКомментрия = Ложь;
КонецЕсли;
ИначеЕсли Символ = """" Тогда
ВнутриКавычек = не ВнутриКавычек;
ИначеЕсли ВнутриКавычек Тогда
Продолжить;
ИначеЕсли Символ = "/" и Сред(Стр, i+1, 1) = "/" Тогда
ВнутриКомментрия = Истина;
i = i + 1;
Иначе
Накопитель = Накопитель + Символ;
ДлинаНакопителя = ДлинаНакопителя + 1;
Если ДлинаНакопителя = ДлинаПодстроки и Накопитель = Подстрока Тогда
Возврат i - ДлинаПодстроки + 1;
ИначеЕсли Накопитель <> Лев(Подстрока, ДлинаНакопителя) Тогда
Накопитель = "";
ДлинаНакопителя = 0;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат 0;
КонецФункции
Функции CompileCode и toCode выделены из Lambda, потому что будут нужны отдельно. Кроме этого используется вспомогательная функция FindWithinCode, которая работает как команда Найти, но игнорирует стрoки внутри строки и комментарии. Например, в возможной конструкции Возврат "Была выполнена команда Возврат;"; при "компиляции" часть "Была выполнена команда Возврат;" должна остаться как есть.
Новые возможности
Используя функцию Lambda можно делать универсальные инструменты.
//Функция вызывает Код для каждого элемента Коллекции. Текущий элемент в Коде находится в переменной _1
//Если Код возвращает значение отличное от Null, в коллекции элемент заменяется.
//
//Например:
// Сообщить каждое значение: ForEach({Массив}, "Сообщить(_1)");
// Умножить каждое четное значение на 3: ForEach({Массив}, "Если _1 % 2 = 0 Тогда Возврат _1 * 3; КонецЕсли;");
//Параметры:
// Коллекция - Массив - пока только массив
// Код - Строка - текущий элемент коллекции находится в переменной _1.
// Возврат значения отличного от Null изменит элемент в коллекции
// _2 - произвольное значение - ..._n Нумерованные параметры можно использовать в Коде
//
Функция ForEach(Коллекция, знач Код, _2=Неопределено, _3=Неопределено, _4=Неопределено)
Код = "#" + CompileCode(Код);
Для i = 0 по Коллекция.ВГраница() Цикл
Значение = Lambda(Код, Коллекция[i], _2, _3, _4);
Если Значение <> null Тогда
Коллекция[i] = Значение;
КонецЕсли;
КонецЦикла;
Возврат Коллекция;
КонецФункции
//Функция возвращает коллекцию, состоящую из элементов Источника, которые удовлетворяют условию описанному в Коде.
//Текущий элемент в Коде находится в переменной _1
//
//Например:
// Отобрать четные числа: Filter({Массив}, "Возврат _1 % 2 = 0;");
// Отобрать строки, набранные заглавными буквами: Filter({Массив}, "Возврат _1 = ВРЕГ(_1);");
// Отобрать элементы, между параметрами _2 и _3 включительно: Filter({Массив}, "Возврат _2 <= _1 и _1 <= _3;", {Значение _2}, {Значение _3});
//
//Параметры:
// Источник - Массив - пока только массив
// Код - Строка - код должен возвращать значение, которое можно преобразовать в Булево
// _2 - произвольное значение - ..._n Нумерованные параметры можно использовать в Коде
//
Функция Filter(Источник, знач Код, _2=Неопределено, _3=Неопределено, _4=Неопределено)
Результат = новый Массив;
Код = "#" + CompileCode(Код);
Для каждого Элемент из Источник Цикл
Если Булево(Lambda(Код, Элемент, _2, _3, _4)) Тогда
Результат.Добавить(Элемент);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Цена
Заметно облегчая написание и чтение кода, данные анонимные функции, конечно, замедляют работу программы. Разница между вызовом классического кода и такого же, но командой Выполнить, минимум в 10 раз! На моих тестах замедление доходило почти до 25 раз. Но это всего лишь означает, что функции, созданные по данной технологии должны вызываться меньшее количество раз. Например, мою функцию ForEach можно переписать так, чтобы цикл был внутри лямбда-кода, тогда лишние сотые доли секунды, нужные директиве Выполнить на интерпретацию станут незаметными.
Отладка лямбда-кода затруднительна. Но анонимные функции не должны быть сложными.
«Боже! Боже! Это настолько нестандартно! Так на 1С не пишут! Кто нам позволит?» — скажут зануды. Вообще-то платформа 1С ценна не красотой и богатством синтаксиса, а распространенностью. А программирование само по себе подразумевает создание нужных абстракций, упрощающих работу. Я всего лишь планирую добавить десяток маленьких, но мощных функций, которые сильно увеличат возможности выражения мысли при кодировании.
Перспектива
Головокружительная! Уже сейчас я закончил функции, которые позволяют создавать специальные структуры, которые можно поместить в переменные и вызвать в другом месте. Эти структуры-функции можно вставлять в другие универсальные коллекции и вызывать с доступом к самому объекту-носителю (как self в Python или this в JS). Таким образом остается написать инструменты, которые будут понимать, что делать со свойством "Prototype" у объекта, и здравствуй, ООП!
// Тестируемый сейчас вариант создания и вызова функций
// newFunction(Параметры, Код) - создает специальную структуру
// Call(Структура, [Параметры]) - вызывает переданную функцию либо функцию из свойства Структуры
// Можно создать "функцию" и поместить её в переменную. Обычный код был бы таким:
// Функция ПервыйВВыборке(Выборка, ЗначениеПоУмолчанию=Неопределено)
// Возврат ?(Выборка.Следующий(), Выборка, ЗначениеПоУмолчанию);
// КонецФункции
//
ПервыйВВыборке = newFunction("Выборка, ЗначениеПоУмолчанию=Неопределено", // параметры функции
"Возврат ?(Выборка.Следующий(), Выборка, ЗначениеПоУмолчанию);" // код функции
);
Выборка = КакойТоКодДляПолученияДанных();
Call(ПервыйВВыборке, Выборка); // Данные выборки или Неопределено
Call(ПервыйВВыборке, Выборка, Ложь); // Данные выборки или Ложь
// Можно назначить структуре "метод"
_Объект = новый Структура("Имя, Фамилия, Представиться",
"Anton",
"Progma",
newFunction("Начало=`Hello! `", "Сообщить(Начало + `My name is ` + _.Имя + ` ` + _.Фамилия);"
)
Call(_Объект, "Представиться", "Hi."); // Hi.My name is Anton Progma
Call(_Объект, "Представиться"); // Hello! My name is Anton Progma
Пока этому всему пара суток отроду. Буду рад любым объективным мнениям. Планирую выпустить еще минимум 2 статьи по данной теме:
Вспомогательные инструменты для упрощения кодирования и чтения.
Функции первого класса, прототипы, наследование и, возможно, замыкания.
VladC
KISS!!!.. Если хочется лямбд, то что угодно, где лямбды являются нативной сущностью, но НЕ 1с, а за такой код я бы прощался с сотрудником после пары проигнорированных предупреждений, т.к. подобный код будет просто не поддерживаемым.
qw1
Сильно зависит от места работы. Если у вас 100500 1с-ников, конечно, все они должны быть заменямыми винтиками, тут никакие выкрутасы недопустимы.
А если программистов всего 3, и один хорошо знает бизнес-процессы (и сам их создаёт), постоянно помогает пользователям решать их задачи (кастомные запросы и выгрузки, полезные кнопочки), то пусть развлекается. Здесь и без лямбд низкий бас-фактор, а такая свобода будет хорошим стимулом оставаться в организации. Нематериальная мотивация.
Win08
Даже если он всего один. Нафиг. Люди имеют свойство болеть, уходить в отпуск, менять работу и еще 100500 различных вариантов.
За написание кода, который приводит к появлению в вакансиях требования «умение читать чужой код» — надо выгонять.
И не только в 1С. Смотри какой я крутой и в одну строчку запихал 100500 функций, процедур, циклов, условий и еще черт знает чего — нафиг оно надо?! Это не дизайн, это украшательство. Кроме понтов, это ничего не дает. Читаемость, по факту, не улучшается, причем даже тот, кто писал, сам, через год не может вспомнить, что он нам намудрил. Сокращение объема кода весьма сомнительно.
qw1
Вот есть у вас работник Вася. Денег много не просит, работу работает, но вот развлекается всякими лямбдами. Ну, уволите вы его. Наймёте нового, который пока не понимает в ваших процессах, работает от звонка до звонка, никакой самодеятельности, но и никакой инициативы. Да ещё и денег попросит в 1.5 раза больше, потому что для него работа — это не развлечение, он сюда пришёл зарабатывать, а не лямбды писать. Значит, надо брать двоих на это место, т.к. инициативы меньше, надо больше формализовывать и лучше ставить задачи.
Я бы на месте руководителя вас бы уволил, за такие вредительские для предприятия решения.
oxidmod
Лучше чуть более высокие, но запланированные расходы, чем внезапные и не запланированные
qw1
Обычно бюджет уже попилен и поделен. Не каджый руководитель готов вкинуть много денег в мифическую «стабильность» (отрывая от себя), тем более, когда всё и так хорошо работает.
Win08
Так да, и пользы приносит бизнесу в 3 раза больше, и проблем не создает — чего бы ему не платить в 1,5 раза больше?
Вообще не понятно, почему если лямбды не пишет то никакой самостоятельности?
А если лямбды пишет, но работает от звонка до звонка, самостоятельности ни какой, инициативы ни какой — держать его за лямбды?
AntonProgma Автор
Узбагойтесь. Я пишу лямбды, на хорошем счету на работе и получаю денег не меньше остальных :)
CrushBy
А производительность такого подхода замеряли?
Помню давно, когда писал на Visual Foxpro, там тоже были такие понятия как макроподстановка (когда можно было выполнить конкретную строку кода, которая хранилась в переменной), а также потом появилась функция EXECSCRIPT, куда можно было передать любую программу, она компилировалась на лету и выполнялась.
Так вот макроподстановка была в 8 раз медленнее, чем обычная строка кода, а EXECSCRIPT — в 25 раз.
IMnEpaTOP
Так вроде автор об этом написал и у него цифры похожие:
"Разница между вызовом классического кода и такого же, но командой Выполнить, минимум в 10 раз! На моих тестах замедление доходило почти до 25 раз. "
CrushBy
А ну да, точно. Просто код 1С для меня не очень привычен, и я не очень понял к чему это относилось.
Забавно, что иногда подход с компиляцией кода мог быть даже быстрее, чем классический. Например, мы делали такие оптимизации, что когда много ветвлений и условий в программе (в зависимости от каких-то внешних параметров/настроек), то выгоднее было сначала сгенерировать код с учетом всех этих настроек, а затем его выполнить. Это было в некоторых случаях значительно быстрее, чем когда внутри FOR/SCAN на каждой записи проверялись бы эти условия.
AntonProgma Автор
Такой код - первый вариант. Но не вижу проблем с оформленным комментариями кодом на сотню строк, если сравнивать его с сотнями тысяч строк "поддерживаемого" типового кода с запросами на 10 страниц прокрутки. Читать же можно, там по-русски почти все! Я - программист, делаю нужные инструменты. А менять работу из-за того, что чего-то в языке не достаёт, так где же работать тогда?! Но, повторюсь, конкретно этот код - эксперимент. И даже устарел за время модерации.
Уволить программиста за проектирование инструментов? Интересно тут.
VladC
По-моему вы пытаетесь подменить понятия, либо просто путаете теплое с мягким, т.к. разницы не видите, не знаю какой ваш вариант, но то что вы сделали инструментом не является. Это просто подход к написанию кода, а не инструмент, причём очень плохой подход, как минимум крайне не читабельный, который уже на старте нарушает такую базовую вещь как KISS. Плюс ко всему проблемы с производительностью, о которых вы сами упомянули, у 1С и так производительность плачевная, а с вашим подходом и производительность ещё больше деградирует и сопровождаемость. Такие вещи хорошо делать в целях академического интереса, но пытаться выдать их за новый подход или инструмент это… как бы помягче сказать… не взлетит и нафиг никому не нужно, потому что не решает ни одной проблемы, прежде всего бизнеса.
AntonProgma Автор
Я вовсе не "продаю" это и не навязываю. Делюсь с коллегами идеей на тематическом сайте. Мне дальше интересно её развить. А кому нет - продолжат жить без неё, делая дело, как удобно им. Я просто хотел уточнить, что в конечном счёте планируются вызовы типа Filter в одну-строчки. Если это не читаем, то уж не знаю, что читаем.
AntonProgma Автор
Два примера! Уже привёл. Если вы имеете в виду, рассказать, как на этом заработать, то пока не придумал)
AntonProgma Автор
Я как раз и хотел узнать конкретику Кошмара) думал, хоть здесь объяснят
myr4ik07
Приведите пример использования
Do-mi-nic
Я бы этот кошмар в продакшен тащить не стал.
Перспектива такой код поддерживать мне видится крайне сомнительной затеей.
anonymous
Где же здесь облегчение написания и чтения кода?
И так клянут разработчиков типового функционала, типа БСП, за излишнюю усложненность кода в угоду универсальности. А если кто-то ещё и такие навороты начнёт делать...
AntonProgma Автор
Что тут скажешь? Используйте то, что понятно, а что не понятно не используйте.
Я исхожу из того, что написание и чтение Filter вполне прозрачны. На другом ресурсе коллега доказывал, что выгоднее писать цикл в лоб, как обычно. Но он в собственном примере из 20ти строк так и не смог найти ошибки. Меньше буков, меньше ошибок!
VladC
вот поэтому подобные вещи это лютое зло, другой программист вообще может тучу времени потратить и в разумные сроки не до конца понять что тут делается, нафиг таких писателей и нафиг такие примеры кода. Умный программист пишет просто и доступно, идиот — с заковырками, типа «посмотрите как я умный».
AntonProgma Автор
Если этот ваш умный программист выносит в функции повторяющиеся код, а потом вызывает с параметрами, то перед вызовом функцией с текстом инструкции тоже не должен спасовать. Принципиальной разницы в чтении никакой.
VaalKIA
Можете не заливать, что у вас хорошо получилось сдлеать ForEaсh и Filter, и поэтому практичность — доказана. Выглядит ужасно и помимо этого, вы фактически сделали метаязык и не важно, что служит базисом. Поэтому, вам, справедливо замечают, о сомнительной применимости.
Не понял, какие проблемы у вас с фиксированным количеством параметров, ибо передавать как структуру, можно конструируя их прямо на месте в нужном количестве.
Ну и собственно, пара моментов: goto вам уже намекнуло на антипаттерн, а передача подпрограмм в виде текста, это полный бред, ибо полностью выключает IDE для этих кусков, не говоря уже про экранирование и верификацию. Для запросов (аналогичный текстовый джихад), есть хотя бы конструктор и разумные люди давно прокляли адептов ЗУПа, которые даже такие вещи превратили в лютую хрень из условных конкатенаций клочков и инжекций каких-то символов и замен на лету, отполированных менеджерами временных таблиц. Тоже весьма «гибкая система» (гори она в Аду), не уподобляйтесь им, а включите мозг.
P. S. Жду вторую статью, поскольку испытываю двойственные чувства к функциональщине и частенько посматриваю в материалы не нагруженные функциональной терминологией.
AntonProgma Автор
Вы любите читать и хотите написать комментарий к следующей статье. Ок.
VaalKIA
Если для вас в этом комменте 0 информации, то нет, конкретно вам, к следующей статье — не хочу, так что хреновый из вас телепат.
P. S. Я вам описал конкретный кейс редактирования языка запросов, представленных как строка, и это очень хреновая практика, аналогичная у вас, эсли вы не способны понять такую простую аналогию, то нам не о чем разговаривать.
AntonProgma Автор
Предположу, что вы передумали.
LARII
Как по мне, вместо ФП(каррирования, денотации) получился какой-то Франкенштейн, который с лямбдами использует псевдо ООП.
AntonProgma Автор
Вы торопитесь! В этом примере даже псевдо ООП не реализовано еще.
iliabvf
Ну я понимаю на infostart, а тут то зачем мучать людей? Изучите C++, напишите на нем внешнюю компонету для 1С, напиши плагин или фронт на JS, больше пользы будет.
AntonProgma Автор
Вот честно не понимаю, почему люди мучаются? У меня получается игнорировать неинтересные лично мне темы.
Neikist
Я вот тоже не понимаю зачем вы мучаетесь, просто свалите с 1с на что то нормальное. Где те же замыкания/лямбды из коробки есть. Я о таком поступке не жалею.
З.Ы. Уже писал на ИС, но для истории и тут оставлю.
У решения две проблемы:
1) Производительность, ибо выполняется интерпретация при каждом выполнении, в отличии от обычного кода который компилируется после первого прохода.
2) Безопасность, ибо при невнимательном обращении позволяет инъекции произвольного кода на сервер.
AntonProgma Автор
Я надеюсь, мы не будем сюда переносить всю историю с других ресурсов. В 1С нет функции Split в нормальном понимании (что строку обратно можно собрать командой Join). Но при необходимости все пишут функцию с нужным пониманием разделителя, а не уходят в среду, где все уже есть. Написать анонимные функции оказалось не прямо уж так сложно, когда мне понадобилось.
К тому же я в свободное время развиваю идею. Скорость работы теперь отличается в 3-6 раз, а не в 10-25. На счёт безопасности - вопрос архитектуры. Разработчику нужно как-то объяснить, что ждать на сервере с клиента код для выполнения - опасно. Предполагается, что лямбда-код выполнится в той среде, откуда вызван (клиент-клиент или сервер-сервер). Параметры используются, как есть. То есть, строки с инструкциями, переданные с клиента как параметры, останутся строками, а не инструкциями.
Я стараюсь трезво смотреть на эту идею. Она явно не привычна одинэсникам, и в то же время не считается интересной для адептов тех языков, где функции первого класса уже есть. Меня никто не понимает :(. Но это не означает, что я не могу опубликовать статьи. Кто-то расценит это как курьез из г и п, кто-то - как занятный прикол, кто-то может найти практическое применение. Но в любом случае вопрос будет рассмотрен,а это уже хорошо для сообщества.
Neikist
Сообщество и вендор в случае 1с очень закостенелы. Сколько они добавляли нормальную асинхронность? При этом сообщество даже тут на хабре постоянно доказывала что ОписаниеОповещения это максимум того что нужно, и никакие async/await не нужны.
Потому и советую перейти на что то получше, в 1с вы не дождетесь качественных улучшений в адекватные сроки. Скорее всего лямбды/замыкания/какое то подобие ооп в 1с появится, но лет через 15-20, если платформа еще жива будет.
В случае с замыканиями там еще и техническая проблема есть потому как сборщик мусора в 1с на подсчете ссылок, а не трассирующий. И потому с замыканиями будет сложно следить за памятью прикладным разработчикам. Кстати непонятно почему разработчики платформы трассирующий сборщик мусора не добавят, ведь подсчет ссылок с их проблемой зацикливания в платформе подразумевающей что разработчикам не нужно задумываться о низких уровнях — это странно и явно проблем добавляет.
AntonProgma Автор
И я так думаю.
qw1
AntonProgma Автор
Вероятно. Но, кажется, я ответил. Если этот параметр ожидается именно, как параметр, то код будет: filter(массив, "_1 = _2", ПараметрОтЮзера). Это означает, что сравнение будет производиться со строкой, и инструкции инъекции не будут выполнены. А если программа спроектирована таким образом, что вставляет код, полученный из вне, то, извините, это не проблема технологии анонимных функций.
qw1
Это требует немного большего погружения в созданную вами библиотеку (так с наскоку и не подумаешь, что тут может быть параметр).
И довольно нелогично… _1 = текущий элемент фильтра, _2 = первый параметр… WTF?
AntonProgma Автор
Я не рассматривал filter и ForEach как продукт. Это просто примеры возможного использования анонимных функций. Ну и само ядро работы с лямбдами уже сильно поменялось. В следующих публикациях останется и разовьется идея, но код поменяется