Упростить синтаксис ламбда-выражений

Дмитрий
Дмитрий

Существующие лямбда-функции порой довольно многословны. Что если немного упростить их синтаксис. Имею ввиду не вырезать то, что есть, а добавить новый синтаксис, а именно:

1. Сделать опциональным указание типа параметра

2. Убрать return из тела лямбда-функций

Насчет первого - идея не нова. Например на cppcon 2014 Герб Саттер уже как-то предлагал похожий вариант для range-for loop. Типа такого:

for(item : collection) {}

Не уверен, но по всей видимости это должно было интерпретировать как auto&& item. По аналогии можно сделать и в лямбдах. (Можно ли?)

Насчет второго - можно было бы последнее выражение без ';' трактовать как возвращаемое значение (примерно как в Rust). Правда не уверен, что здесь нет каких-нибудь подводных камней по типу 'существующая грамматика уже настолько сложна, что это все не получится реализовать' или 'не будет обратной совместимости'.

 

По итогу, вместо этого:

auto greater = [](auto&& x, auto&& y){ return x > y; };

Мы получим это:

auto greater = [](x, y){ x > y };
1
рейтинг
5 комментариев
Andrey Davydov
Это предлагалось в http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r0.html раздел "Omission of type names in lambdas". Proposal был rejected комитетом. Основная проблема, с моей точки зрения (мотивировку комитета я не знаю): для того чтобы определить является ли `x` именем аргумента (с опущенным типом) или типом аргумента придется делать дополнительный lookup. Забавное проявление этой проблемы: (аrgs...) будет означать (args _, ... /* C variadic args*/), если args резолвится в тип и (auto && ... args) иначе.
Andrey Davydov
Antervis
Andrey Davydov, в случае с args по идее должно быть: [](...args) { } а не [](args...) { }. А т.к. префиксное троеточие нигде не используется, объявление однозначно. Касательно lookup - по идее, такие вещи не должны сильно портить картину. Например, из-за most vexing parse код типа void a(b()); может интерпретироваться двумя способами если b - тип и еще одним если b - переменная
Antervis
Andrey Davydov
Antervis,
> в случае с args по идее должно быть: [](...args) { } а не [](args...) { }
в proposal'е на который я ссылался было постфиксное многоточие. В вашем варианте другая "readability issue" (на мой взгляд) -- [] (...args) -- generic-лямбда, но если опустить имя параметра (что в данный момент в C++ никогда не меняет сигнатуру функции) получается non-generic lambda с C variadic args.
> Касательно lookup - по идее, такие вещи не должны сильно портить картину. Например, из-за most vexing parse...
Most vexing parse был одной из мотивирующих причин uniform initialization syntax. Хочется уменьшать число случаев контекстно-зависимого parsing'а, а не увеличивать.
Andrey Davydov
Antervis
Andrey Davydov,
> generic-лямбда, но если опустить имя параметра (что в данный момент в C++ никогда не меняет сигнатуру функции) получается non-generic lambda с C variadic args.

точно так же, как и [](x){} примет такое же число таких же аргументов как и [](auto &&){}, но не такое же, как и если "опустить" имя параметра: [](){}. Вообще, многоточие перед именем переменной является скорее частью её определения, а не самостоятельной единицей. Нет такого контекста, где auto..., args... или ...args будет тем же самым, что и убрав auto/args
Antervis
Antervis
я уже писал про "неявный return в конце лямбды". Надо как-то гарантировать, что поведение старого кода не изменится. Моим предложением было, что неявный return если последний ; опущен: { a() } эквивалентно { return a(); }, но не эквивалентно { a(); }
Antervis
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения