?

Log in

No account? Create an account
nyaload

Журнал Пушыстого

Журнал Пушыстого

Previous Entry Share Next Entry
лямбда в C++ - уже работающая реальность
nyaload
_winnie
В питоне у функций сортировки, min(список) есть параметр key, это callback-функция которая говорит, по какому признаку отсортировать. У сортировки есть ещё параметр cmp, callback в котором пользователь задаёт свою функцию сравнения двух величин. Так вот, я им ни разу не воспользовался. Всегда было достаточно key.

В связи с чем обидно, что у C++ных std::sort, std::min_element это указать невозможно, в коде callback нужно указывать в два раза больше чем хочется.

Кстати, в C++ появились лямбда функции, их уже можно использовать в gcc4.что.то.там и Visual C++ 2010.

Теперь что бы найти в массиве наиболее близкий к val можно писать
int *a_min = std::min_element(a_begin, a_end, [=](int x, int y) { return abs(x-val) < abs(y-val); });

Можно в вашу велосипедную корпоративную библиотеку утилит добавить min_by_key, что бы писать
int *a_min = my::min_by_key(array, [=](int x) { return abs(x-val); });

Раньше, что бы воспользоваться уже написаным std::min_element, приходилось писать мего-функтор где-то на страницу кода выше, за пределом экрана. Про boost::* молчу. Это приводило к тому, что рукописный цикл был и читаемей, и проще писался. Единственный алгоритм который сцали писать с нуля - это std::sort. Теперь же можно писать просто и наглядно, при code-review не нужно анализировать, сделали ли типичную опечатку в коде поиска минимума, что будет если список пустой.

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

upd: поторопился, сейчас распространён gcc4.4, а лямбды сделали в gcc4.5, который вот-вот будет в дефолтных дистрибутивах. Надо перепостить это через полгодика :)
Tags: ,


  • 1
Не, ну раньше в с++ можно было сделать функтор, запхнуть в него val переменной, и точно так же вызывать. Другое дело, что синтаксически это дофига кода и проще в цикле.

Это раньше было не так уж и давно (буквально сегодня):
http://rvp74.livejournal.com/181842.html?mode=reply

:)

int main() { struct fun_impl { bool operator() (int a, int b) { return a > b; } } fun; vector<int> a(10); for (size_t i = 0, ilen = a.size(); i < ilen; ++i) a[i] = i; sort(a.begin(), a.end(), fun); copy(a.begin(), a.end(), ostream_iterator<int>(cout, " ")); cout << endl; }
_Winnie C++ Colorizer

да че уж там, for тоже лишний:
:)

class incrementer
{
public:
    explicit incrementer(int cnt, int step = 1) : m_cnt(cnt), m_step(step) {}
    int operator()() { int ret = m_cnt; m_cnt += m_step; return ret; }
private:
    int m_cnt;
    int m_step;
};
...

    generate_n(a.begin(), a.size(), incrementer(0));


> их уже можно использовать в gcc4.что.то.там
gcc 4.5 на сайте кажут. Лямбды ещё не пробовал. Пробовал взятые из Буста байнды, пробовал auto. Многое ещё предстоит попробовать...

на ps3 лямбды нет :(
и неизвестно когда появится и появится ли вообще

в gcc 4.4 ламбду не обнаружил. Рано мне еще ее юзать под Ubuntu 10.04
;)

Упс, надо будет через полгодика этот пост повторить :)

Про boost::* молчу.

Нет уж расскажи! Как оно там?

Вроде бы
int *a_min = std::min_element(a_begin, a_end, abs(_1-val(v)) < abs(_2-val(v)) );
_Winnie C++ Colorizer

и через полгода тоже. Компиляторы которые бы успешно делали loop fusion можно ждать много лет. Всегда есть еще что посчитать том же проходе по данным - тот же максимум для примера.

Можно написать библиотеку на С++.
Сам уже пробовал делать так, что
v = fold(f, map(g, v));

срабатывало in-place за один проход.

(Deleted comment)
у нормальных поцонов gcc4.5 уже есть ;)

(Deleted comment)
если поглядеть на темпы, которыми обновляется моя рабочая среда, этот пост надо будет перепощивать не через полгодика, а лет через пять :)

Стабильность!

Та же хня у мелкомягких. Не соберусь дома поменять VS 2008 на VS 2010, чтобы отказаться от boost::bind (кодогенерация на темплейтах - есть зло и тормоз компилятора, лучше уж нормальный внешник кодогенератор прикрутить)

Скорее всего, вы будете очень разочарованы скоростью работы.

лямбда в C++ - уже работающая реальность

Вот и Саттер говорит: Lambdas, Lambdas Everywhere! (Отсюда.)

Посмотрел на Lambda в С++ и походу ничего кроме небольшого укорочения записи из неё не выжмешь. Да и то это укорочение опасное, потому как заставляет темплейтами пользоваться. В обычную функцию лямду не передашь. Тип Lambda не объявишь. Лично моя точка зрения - кодогенерация пошла не в ту сторону.

>. В обычную функцию лямду не передашь. Тип Lambda не объявишь.
Есть boost::function или свой велосипедный Command, которые заменяют шаблоны на runtime-полиморфизм

Ну и это не особо важно, когда надо только что бы удобней было делать find/transform/min_element/sort.

Edited at 2010-11-29 11:26 am (UTC)

  • 1