OneScript icon indicating copy to clipboard operation
OneScript copied to clipboard

Лямбды

Open nixel2007 opened this issue 8 years ago • 22 comments

Лямбда-функции решат все ваши проблемы (с)

Концепт

МойМассив = Новый Массив;
МойМассив.Добавить(1);
МойМассив.Добавить(2);

МойМассив.ДляКаждого( (Элемент) => Сообщить(Элемент)) 

// 1
// 2

МойМассив.ДляКаждого( (Элемент) => 
    Лямбда
        Сообщить("Я многострочная лямбда");
        Сообщить(Элемент);
    КонецЛямбды
);

// вместо Лямбда...КонецЛямбды можно попробовать Процедура...КонецПроцедуры, но имхо это смерть для парсера

//в порядке бреда
Процедура МояЛямбда(Элемент)
    Сообщить(Элемент);
КонецПроцедуры

МойМассив.ДляКаждого(МояЛямбда);
// Да-да, функции высшего порядка 

СП в духе Массив.ДляКаждого(Лямда(Элемент)); --- процедура ДляКаждого принимает в качестве аргумента Лямбда-функцию с одним параметром. В качестве параметра передаётся элемент коллекции.

Аналогично для структуры и КлючИЗначение и прочих Соответствий

nixel2007 avatar Apr 06 '17 18:04 nixel2007

//в порядке бреда
Процедура МояЛямбда(Элемент)
    Сообщить(Элемент);
КонецПроцедуры

МойМассив.ДляКаждого(МояЛямбда);

вот это не сработает. МояЛямбда - это имя переменной. такой вот затык в жёлтом синтаксисе

dmpas avatar Apr 06 '17 19:04 dmpas

МояЛямбда - это имя переменной. такой вот затык в жёлтом синтаксисе

Почему нельзя расширить поиск по именам функций? Ты же не сможешь объявить переменную с именем, совпадающим с уже имеющейся процедурой

nixel2007 avatar Apr 06 '17 19:04 nixel2007

Мне давно хочется вариант МойМассив.ДляКаждого(МояЛямбда); но как отличить от переменной? в 1С и 1скрипте вроде как разрешено иметь одно имя для переменной и метода

artbear avatar Apr 06 '17 19:04 artbear

Ты же не сможешь объявить переменную с именем, совпадающим с уже имеющейся процедурой

могу же

dmpas avatar Apr 06 '17 19:04 dmpas

Мне как раз больше нравятся функции высшего порядка. ИМХО они лучше на язык 1С ложатся.

Хотя и варианты с лямбдой очень интересны.

artbear avatar Apr 06 '17 19:04 artbear

Как раз нужно избавиться от всяких обработок оповещения и т.п.

artbear avatar Apr 06 '17 19:04 artbear

а мне нравятся обработки оповещения :) они код делают площе. Повидал я говногода, полюбил 1С за отсутствие всего на свете.

dmpas avatar Apr 06 '17 19:04 dmpas

Да, дает объявить переменную и функцию с одинаковым именем...

nixel2007 avatar Apr 06 '17 19:04 nixel2007

Уймитесь, нехристи! Пишите на ноде :)

А вообще, если вспомнить, что язык 1С - это Basic, переведенный промтом, то кошерный синтаксис должен выглядеть вот-так: https://msdn.microsoft.com/ru-ru/library/bb531253.aspx

EvilBeaver avatar Apr 09 '17 20:04 EvilBeaver

@EvilBeaver если я правильно понимаю, то в 1с-варианте для многострочной лямбды это будет примерно так:

МойМассив.ДляКаждого( Функция (Параметр) 
Сообщить(Параметр);
Сообщить("я многострочная лямбда");
КонецФункции);

nixel2007 avatar Apr 09 '17 20:04 nixel2007

Либо надеяться на корректную расстановку скобок, тогда можно опустить КонецФункции

nixel2007 avatar Apr 09 '17 20:04 nixel2007

Во-первых, предлагаю различать лямбды и функции-объекты.

Лямбда-функция - это вложенная функция, которая видит контекст родительской функции и может "захватывать" (по умному - "делать замыкание") переменных родительской функции. Тут вылезают сразу уши областей видимости, правила замыкания переменных и прочее. См. правила видимости в жаваскрипте.

Тут выходит несложная доработка компилятора и очень большая доработка самой виртуальной машины, ибо там все сложно с областями переменных.

И более простой вариант: объявлять функции как и сейчас, но иметь возможность их передать куда-либо. Т.е. реализовать что-то типа делегатов из мира C#. Это проще, ибо без замыканий. Доработка машины вроде бы не потребуется.

Процедура МоеДействие()
     Сообщить("Привет");
КонецПроцедуры

Действие = Функция(МоеДействие); // чтобы не ломать обратную совместимость Массив = Массив();
Действие(); // вызов

EvilBeaver avatar Apr 10 '17 12:04 EvilBeaver

Процедура МоеДействие()
     Сообщить("Привет");
КонецПроцедуры

Процедура Действие()
// ага, привет!!!
КонецПроцедуры

Действие = Функция(МоеДействие); // чтобы не ломать обратную совместимость Массив = Массив();
Действие(); // вызов

dmpas avatar Apr 10 '17 12:04 dmpas

Тогда и вызов нужно делать типа

Действие = Функция(МоеДействие); // чтобы не ломать обратную совместимость Массив = Массив();
Вызвать Действие(); // вызов

dmpas avatar Apr 10 '17 12:04 dmpas

@dmpas почему?

EvilBeaver avatar Apr 10 '17 12:04 EvilBeaver

Ааа. понял. Ну тот можно пойти по тому пути, что ввести правила вызова:

  • По скобкам сначала вызывается обычная функция (как раньше)
  • Если таковой нет и скобки применены к делегату - вызываем его
  • Если скобки применены к неделегату (Числу, например) - выбрасываем исключение

EvilBeaver avatar Apr 10 '17 12:04 EvilBeaver

По скобкам сначала вызывается обычная функция (как раньше)

Может наоборот лучше делегата сперва вызывать? Перегрузка метода и все такое

Stepa86 avatar Apr 10 '17 12:04 Stepa86

@Stepa86 пример привести можешь, когда именно такое поведение нужно?

EvilBeaver avatar Apr 10 '17 13:04 EvilBeaver

@EvilBeaver Сходу не могу. Но мне кажется более логичным вызывать сперва делегата или вообще падать в исключение в этой ситуации

Stepa86 avatar Apr 10 '17 13:04 Stepa86

У меня один аргумент: описанное мной поведение реализовать проще. Ну и второй аргумент - не доказано (примером) что нужно иное поведение.

EvilBeaver avatar Apr 10 '17 13:04 EvilBeaver

@EvilBeaver для эксперементальной штуки первого аргумента более, чем достаточно

Stepa86 avatar Apr 10 '17 13:04 Stepa86

Оставлю тут ссылку на параллельное обсуждение: https://github.com/tsukanov-as/OneShell/issues/13

dmpas avatar Aug 10 '17 06:08 dmpas