Дают ли lambdas какие-то принципиально новые возможности?
От: Максим Рогожин Россия  
Дата: 04.10.17 07:18
Оценка:
Привет, всем!

Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности? Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?

Например, деструкторы в C++ нельзя заменить никакими средствами языка C.
Отредактировано 04.10.2017 7:27 Максим Рогожин . Предыдущая версия . Еще …
Отредактировано 04.10.2017 7:20 Максим Рогожин . Предыдущая версия .
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: rg45 СССР  
Дата: 04.10.17 07:38
Оценка: +11
Здравствуйте, Максим Рогожин, Вы писали:

МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности? Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?


Просто избавляют от необходимости определять самому новые функции и классы. Ведь фактически любая лямбда — это просто объект автоматически сгенерированного класса с определенным operator(). Если лямбда использует auto в списке формальных параметров, operator() будет шаблонной функцией-членом. Вот и вся магия. Можно обойтись без лямд, ценой ухудшения компактности кода и засорения пространств имен лишними именами.
--
Справедливость выше закона. А человечность выше справедливости.
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: T4r4sB Россия  
Дата: 04.10.17 07:43
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Например, деструкторы в C++ нельзя заменить никакими средствами языка C.


Яб поспорил. Можно, если перегрузить {}, и все объекты объявлять специальным макросом, который добавляет объект в специальный список, а } будет чистить этот список.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Дают ли lambdas какие-то принципиально новые возможности?
От: Mihas  
Дата: 04.10.17 08:53
Оценка:
Здравствуйте, rg45, Вы писали:

R>Можно обойтись без лямд, ... и засорения пространств имен лишними именами.

Шарповый компилятор авто-именует лямбда-функции. В плюсах такого нет?
Re[3]: Дают ли lambdas какие-то принципиально новые возможности?
От: rg45 СССР  
Дата: 04.10.17 10:26
Оценка:
Здравствуйте, Mihas, Вы писали:

R>>Можно обойтись без лямд, ... и засорения пространств имен лишними именами.

M>Шарповый компилятор авто-именует лямбда-функции. В плюсах такого нет?

Разумеется, C++ компилятор так же обеспечивает уникальность имен всех автоматически генерируемых сущностей. Но мы же говорим о том, что будет, если отказаться от лямбд. Или я не понял вопрос?
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Дают ли lambdas какие-то принципиально новые возможности?
От: Mihas  
Дата: 04.10.17 10:33
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>Можно обойтись без лямд, ... и засорения пространств имен лишними именами.

M>>Шарповый компилятор авто-именует лямбда-функции. В плюсах такого нет?
R>Разумеется, C++ компилятор так же обеспечивает уникальность имен всех автоматически генерируемых сущностей. Но мы же говорим о том, что будет, если отказаться от лямбд. Или я не понял вопрос?
Все верно.
Мой вопрос — не аргумент за или против лямбда-функций, а прояснение для себя. Не засоряется пространство имен в мозгу разработчика.
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: Анатолий Широков СССР  
Дата: 04.10.17 10:50
Оценка: +2
Здравствуйте, Максим Рогожин, Вы писали:

МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности? Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?


Поддержка лямбда выражений дала возможность локализации кода в месте обработки или вычисления.
Re: Дают ли lambdas какие-то принципиально новые возможности
От: Alexander G Украина  
Дата: 04.10.17 11:02
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности? Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?


Нет, в бусте сделали их имитацию средствами С++03:

Boost.LocalFunction
Русский военный корабль идёт ко дну!
Отредактировано 04.10.2017 11:09 Alexander G . Предыдущая версия .
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: so5team https://stiffstream.com
Дата: 04.10.17 11:35
Оценка: +1 -1
Здравствуйте, Максим Рогожин, Вы писали:

МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности? Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?


Появилась возможность создавать локальные функции. Без засорения внешнего пространства имен. Например:
void storage_t::drop_subscription_for_all_states(
    const mbox_t & mbox_ref,
    const std::type_index & type_index )
    {
        const key_t key( mbox_ref->id(), type_index );

        auto it = m_map.lower_bound( key );
        auto need_erase = [&] {
                return it != m_map.end() && key.is_same_mbox_msg_pair( it->first );
            };
        if( need_erase() )
        {
            do
                {
                    m_hash_table.erase( &(it->first) );
                    m_map.erase( it++ );
                }
            while( need_erase() );

            mbox_ref->unsubscribe_event_handlers( type_index, owner() );
        }
    }

Здесь need_erase -- это классическая локальная функция, которая имеет доступ к контексту, внутри которого она определена. Другими средствами этого же можно было бы добиться либо определением какой-то дополнительной сущности, хранящей в себе часть контекста. Либо же посредством макросов. Но дополнительная сущность -- это лишняя работа. А макросы -- это зло
Re[2]: Дают ли lambdas какие-то принципиально новые возможности?
От: uzhas Ниоткуда  
Дата: 04.10.17 14:40
Оценка: 1 (1) -1
Здравствуйте, so5team, Вы писали:

S>Появилась возможность создавать локальные функции. Без засорения внешнего пространства имен.

тут согласен

S>Например:

......
S>А макросы -- это зло

ну твоя локальная функция — тоже зло, ибо неявно хватает тот самый контекст
код был бы понятнее, имхо, если бы ты передал хотя бы it в эту функция явно
ну и глубину скоупов можно уменьшить:
void storage_t::drop_subscription_for_all_states(
    const mbox_t & mbox_ref,
    const std::type_index & type_index )
    {
        const key_t key( mbox_ref->id(), type_index );

        auto need_erase = [&] ( auto i ) {
                return i != m_map.end() && key.is_same_mbox_msg_pair( i->first );
            };
            
        auto it = m_map.lower_bound( key );
        if( !need_erase( it ) )
            return;

        do 
        {
            m_hash_table.erase( &(it->first) );
            m_map.erase( it++ );
        }
        while( need_erase( it ) );

        mbox_ref->unsubscribe_event_handlers( type_index, owner() );
    }

ps. маньячные пробелы для аргументов
Re[3]: Дают ли lambdas какие-то принципиально новые возможности?
От: so5team https://stiffstream.com
Дата: 04.10.17 15:07
Оценка: +1
Здравствуйте, uzhas, Вы писали:

S>>Появилась возможность создавать локальные функции. Без засорения внешнего пространства имен.

U>тут согласен

Ну надо же, как нам повезло!

U>ну твоя локальная функция — тоже зло, ибо неявно хватает тот самый контекст

U>код был бы понятнее, имхо, если бы ты передал хотя бы it в эту функция явно
U>ну и глубину скоупов можно уменьшить:

Своим преждевременным return-ом и передачей аргумента в локальную функцию вы усложнили код, наши поздравления.
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: kov_serg Россия  
Дата: 04.10.17 15:08
Оценка: +1
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет, всем!


МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности?

Нет. Принципиально новые возможности это SIMD и #pragma omp и тому подобное.

МР>Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?

Язык полный по тюрингу позволяет реализовать всё, что душе угодно.

МР>Например, деструкторы в C++ нельзя заменить никакими средствами языка C.

Как нельзя? Кто запрещает вызывать функции очистки руками.
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: alpha21264 СССР  
Дата: 04.10.17 15:31
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности?


Разумеется, нет. Любая программа пишется с помощью циклов, условий и вызовов. подпрограмм.

PS.
Я тут две недели пописал на С (без плюсов). Это утомительно.
Но если вспомнить приёмы программирования, которые сам же употреблял двадцать лет назад...
Даже и кода оказывается ненамного больше.

Течёт вода Кубань-реки куда велят большевики.
Re[4]: Дают ли lambdas какие-то принципиально новые возможности?
От: uzhas Ниоткуда  
Дата: 04.10.17 15:39
Оценка: 18 (1) +1 :)
Здравствуйте, so5team, Вы писали:

S>Своим преждевременным return-ом


так в плюсах принято. как только понял, что делать нечего — выходи. в сях по-другому (но мы же претендуем на плюсовый код? ), ибо нет RAII
можно почитать хотя бы тут: https://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement
в swift даже есть клевый guard для этих целей

S>передачей аргумента в локальную функцию вы усложнили код


усложнение — это когда функция без аргументов возвращает то true, то false =)
Re[5]: Дают ли lambdas какие-то принципиально новые возможности?
От: so5team https://stiffstream.com
Дата: 04.10.17 15:53
Оценка: +1
Здравствуйте, uzhas, Вы писали:

U>так в плюсах принято. как только понял, что делать нечего — выходи.


Ну вот в своем коде вы можете делать все, что захотите. Хоть преждевременный return, который легко не заметить, хоть передачу аргументов, хотя это вполовину уменьшает ценность локальной функции. Что угодно.
Re[4]: Дают ли lambdas какие-то принципиально новые возможности?
От: MTD https://github.com/mtrempoltsev
Дата: 05.10.17 04:44
Оценка: +1 -1
Здравствуйте, so5team, Вы писали:

U>>тут согласен


S>Ну надо же, как нам повезло!


У тебя пмс что-ли? Что ты так болезненно реагируешь?

U>>ну твоя локальная функция — тоже зло, ибо неявно хватает тот самый контекст


Согласен с коллегой.

S>Своим преждевременным return-ом и передачей аргумента в локальную функцию вы усложнили код, наши поздравления.


По-моему наоборот.
Re: Дают ли lambdas какие-то принципиально новые возможности?
От: scf  
Дата: 05.10.17 05:20
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет, всем!


МР>Добавление лямбда-функций и замыканий дает языку C++ какие-то принципиально новые возможности? Или все что можно сделать используя лямбда-функции и замыкания можно было делать и раньше другими средствами языка?


МР>Например, деструкторы в C++ нельзя заменить никакими средствами языка C.


Лямбды позволяют активно использовать в коде функции высшего порядка, т.е. функции, принимающие функции в качестве аргументов.

std::for_each(v.begin(), v.end(),
 [](auto i)
 {
   std::cout << i;
 }
 );


Если бы STL не был приветом из 90х, этот код выглядел бы вот так:

v.for_each([](auto i) 
{
  std::cout << i;
});


Но в плюсах традиционно плохо с библиотеками
Re[2]: Дают ли lambdas какие-то принципиально новые возможности?
От: MTD https://github.com/mtrempoltsev
Дата: 05.10.17 05:51
Оценка:
Здравствуйте, scf, Вы писали:

scf>std::for_each(v.begin(), v.end(),


scf>Если бы STL не был приветом из 90х, этот код выглядел бы вот так:


scf>v.for_each([](auto i)


Весь смысл STL в разделении данных и алгоритмов, для того чтобы работали многие алгоритмы требуются итераторы произвольного доступа. Я не уверен хорошо это или плохо, с одной стороны код многословней, с другой иначе пришлось бы дублировать алгоритмы в контейнерах.
Re[5]: Дают ли lambdas какие-то принципиально новые возможности?
От: so5team https://stiffstream.com
Дата: 05.10.17 06:11
Оценка: 3 (1) +2
Здравствуйте, uzhas, Вы писали:

U>так в плюсах принято. как только понял, что делать нечего — выходи. в сях по-другому (но мы же претендуем на плюсовый код? ), ибо нет RAII

U>можно почитать хотя бы тут: https://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement
U>в swift даже есть клевый guard для этих целей
U>усложнение — это когда функция без аргументов возвращает то true, то false =)

Похоже, что некоторые не понимают очевидных вещей, поэтому поясним развернуто.

1. Очевидно, существует, как минимум три способа записать и использовать локальную функцию need_erase:

первый:
auto need_erase = [&](const auto & k, const auto & i) {...};
if(need_erase(key, it))...


второй:
auto need_erase = [&](const auto & i) {...};
if(need_erase(it))...


третий:
auto need_erase = [&]{...};
if(need_erase())...


Второй способ, т.е. предпочитаемый вами, в данном случае выглядит наименее логичным и выгодным, потому что:

2. need_erase не нуждается в аргументах, поскольку ее можно рассматривать как аналог булевой переменной вот в таком варианте записи кода:
bool storage_t::is_valid_iterator_to_same_mbox(const key_t & key, const map_t::iterator & it)
    {
        return it != m_map.end() && key.is_same_mbox_msg_pair( it->first );
    }
void storage_t::drop_subscription_for_all_states(
    const mbox_t & mbox_ref,
    const std::type_index & type_index )
    {
        const key_t key( mbox_ref->id(), type_index );

        auto it = m_map.lower_bound( key );
        bool need_erase = is_valid_iterator_to_same_mbox( key, it );
        if( need_erase )
        {
            do
                {
                    m_hash_table.erase( &(it->first) );
                    m_map.erase( it++ );
                    need_erase = is_valid_iterator_to_same_mbox( key, it );
                }
            while( need_erase );

            mbox_ref->unsubscribe_event_handlers( type_index, owner() );
        }
    }

Т.е. need_erase -- это показатель текущего статуса хода выполнения алгоритма. На каждом шаге этот статус обновляется и проверяется. Лямбды в виде локальных функций позволяют записать это максимально лаконично, но при этом не потеряв в понятности кода. Для чего именно этот пример и был приведен.

Еще по поводу функций без параметров, возвращающих то true, то false: попробуйте применить этот же аргумент к std::vector::empty(), например.

3. В C++ не обязательно придерживаться принципа "единственный return" на всю функцию, в отличии от C и других процедурных языков. Но это не значит что в C++ return из середины функции нужно делать всегда. Правило единственнго return-а появилось очень давно (возможно, еще до появления C++) и относилось оно не столько к проблеме очистки ресурсов, сколько к понятности кода функции. В данном случае нам было принципиально важно, чтобы в коде было четко видно, что цикл с последующим unsubscribe_event_handlers должен выполняться только, если вообще было найдено что-то для удаление. Запись этих действий в блоке под if-ом показывает это намного более явно, чем преждевременный return в середине функции.

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


Собственно к чему это все было рассказано: принятые решения имеют свои обоснования, код был написан так, как он был написан не потому, что так получилось или просто так захотелось. Вас эти аргументы могут не убедить. Равно как и нас ваши аргументы. Следовательно, здесь спор будет идти об эстетических пристрастиях. А это, во-первых, бессмыслено. И, во-вторых, никак не относится к первоначальному посылу о том, что лямбды в C++11 сделали возможным написание локальных функций, имеющих полный доступ к локальному контексту.
Re[4]: Дают ли lambdas какие-то принципиально новые возможности?
От: AlexRK  
Дата: 05.10.17 07:00
Оценка:
Здравствуйте, so5team, Вы писали:

S>Своим преждевременным return-ом и передачей аргумента в локальную функцию вы усложнили код, наши поздравления.


А по-моему код упростился. Захват контекста это зло.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.