Какова мотивация лямбда-выражений C ++ 11?

Swift 4 решение, которое работает для меня, чтобы получить URL последнего изображения в Photo Library:

let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions).lastObject
PHImageManager().requestAVAsset(forVideo: fetchResult!, options: nil, resultHandler { (avurlAsset, _, _) in
    if let newObj = avurlAsset as? AVURLAsset {
        print(newObj.url)
    }
})

Надеюсь, что это поможет!

20
задан nbro 30 October 2016 в 21:52
поделиться

8 ответов

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

41
ответ дан 29 November 2019 в 22:25
поделиться

Преимущество состоит в том, что является наиболее важным при написании компьютерных программ: более простой для понимания код . Мне не известны какие-либо соображения по поводу производительности.

C ++ в определенной степени позволяет выполнять Функциональное программирование . Подумайте об этом:

std::for_each( begin, end, doer );

Проблема в том, что функция (объект) doer

  1. указывает , что делается в цикле
  2. , но в некоторой степени скрывает то, что на самом деле сделано ] (необходимо найти реализацию operator () функционального объекта)
  3. должно быть определено в другой области , чем std :: for_each call
  4. содержит определенное количество шаблонного кода
  5. часто является отбрасываемым кодом , который не используется ни для чего, кроме этой конструкции с одним циклом

Лямбда-выражения значительно улучшают все эти ( а может еще что-то забыл).

43
ответ дан 29 November 2019 в 22:25
поделиться

Само по себе повышения производительности нет, но потребность в лямбда-выражении возникла как следствие широкого распространения STL и его дизайнерских идей.

В частности, алгоритмы STL часто используют функторы. Без лямбда эти функторы должны быть заранее объявлены для использования. Лямбда-выражения позволяют иметь «анонимные» функторы на месте.

Это важно, потому что есть много ситуаций, в которых вам нужно использовать функтор только один раз, и вы не хотите давать ему имя по двум причинам: вы не хотите загрязнять пространство имен и в в этих конкретных случаях имя, которое вы даете, либо расплывчатое, либо очень длинное.

Я, например, много использую STL, но без C ++ 0x я использую гораздо больше циклов for (), чем алгоритм for_each () и его собратья. Это потому, что если бы я использовал вместо этого for_each (), мне нужно было бы получить код из цикла и объявить для него функтор. Кроме того, все локальные переменные перед циклом не будут доступны, поэтому мне нужно написать дополнительный код, чтобы передать их в качестве параметров конструктору функтора или другому эквиваленту. Как следствие, я стараюсь не использовать for_each (), если нет сильной мотивации, иначе код был бы длиннее и труднее читался.

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

13
ответ дан 29 November 2019 в 22:25
поделиться

IMO, самое важное в лямбдах - это то, что они удерживают связанный код рядом друг с другом. Если у вас есть такой код:

std::for_each(begin, end, unknown_function);

Вам нужно перейти к unknown_function, чтобы понять, что делает код. Но с помощью лямбды логика может быть собрана вместе.

9
ответ дан 29 November 2019 в 22:25
поделиться

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

Можно утверждать, что это помогает в удобочитаемости кода (если ваш функтор объявлен встроенным там, где он используется).

8
ответ дан 29 November 2019 в 22:25
поделиться

Хотя я считаю другие части C++0x более важными, лямбды - это больше, чем просто "синтаксический сахар" для объектов функций в стиле C++98, потому что они могут захватывать контексты, и они делают это по имени, а затем они могут брать эти контексты в другом месте и выполнять. Это нечто новое, а не то, что "компилируется быстрее/медленнее".

#include <iostream>
#include <vector>
#include <functional>
void something_else(std::function<void()> f)
{
        f(); // A closure! I wonder if we can write in CPS now...
}
int main()
{
        std::vector<int> v(10,0);
        std::function<void ()> f = [&](){ std::cout << v.size() << std::endl; };

        something_else(f);
}
5
ответ дан 29 November 2019 в 22:25
поделиться

Что ж, сравните это:

int main () {
    std::vector<int> x = {2, 3, 5, 7, 11, 13, 17, 19};

    int center = 10;
    std::sort(x.begin(), x.end(), [=](int x, int y) {
        return abs(x - center) < abs(y - center);
    });

    std::for_each(x.begin(), x.end(), [](int v) {
        printf("%d\n", v);
    });

    return 0;
}

с этим:

// why enforce this to be defined nonlocally?
void printer(int v) {
    printf("%d\n", v);
} 

int main () {
    std::vector<int> x = {2, 3, 5, 7, 11, 13, 17, 19};

    // why enforce we to define a whole struct just need to maintain a state?
    struct {
        int center; 
        bool operator()(int x, int y) const {
            return abs(x - center) < abs(y - center);
        }
    } comp = {10};

    std::sort(x.begin(), x.end(), comp);

    std::for_each(x.begin(), x.end(), printer);

    return 0;
}
2
ответ дан 29 November 2019 в 22:25
поделиться

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

Чаще всего программист выполняет итерации над рядом элементов (поиск элемента, накопление элементов, сортировка элементов и т.д.). Используя функциональный стиль, вы сразу видите, что программист намерен сделать, в отличие от использования циклов for, где все "выглядит" одинаково.

Сравните алгоритмы + лямбда:

iterator longest_tree = std::max_element(forest.begin(), forest.end(), [height]{arg0.height>arg1.height});
iterator first_leaf_tree = std::find_if(forest.begin(), forest.end(), []{is_leaf(arg0)});
std::transform(forest.begin(), forest.end(), firewood.begin(), []{arg0.trans(...));
std::for_each(forest.begin(), forest.end(), {arg0.make_plywood()});

со старыми добрыми циклами for;

Forest::iterator longest_tree = it.begin();
for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
   if (*it.height() > *longest_tree.height()) {
     longest_tree = it;
   }
}

Forest::iterator leaf_tree = it.begin();
for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
   if (it->type() == LEAF_TREE) {
     leaf_tree  = it;
     break;
   }
}

for (Forest::const_iterator it = forest.begin(), jt = firewood.begin(); 
     it != forest.end(); 
     it++, jt++) {
          *jt = boost::transformtowood(*it);
    }

for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
    std::makeplywood(*it);
}

(Я знаю, что этот кусок кода содержит синтаксические ошибки)

.
2
ответ дан 29 November 2019 в 22:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: