Pull to refresh

Comments 83

Я только начал вникать в С++0x, но уже сожалею, что убрали концепты. Спасибо за разъяснение. Надеюсь на продолжение.
Спасибо Вам за оценку. Следующей статьёй я думал написать о ссылках на rvalue (rvalue references) также из будущего стандарта.
Да, да, обязательно пишите — у вас это прекрасно получается. Я хоть и почитал уже довольно много про это, но лишним такое описание, как тут, не будет. Ждём!
Обязательно пишите, статья получилась очень хорошая и толковая (и потом — желания курить новый стандарт я в себе так и не нашел, а тут все понятно и доступно).
Пишите пожалуйста. Из нового стандарта rvalue refs — это самое мутное для меня, пожалуй. С удовольствием прочитаю.
Для простоты можете представить, что это «ссылка на ссылку» (по аналогии «указатель на указатель»).

Мне вот интересно, что GooRooнапишет, покольку я себе примерно представляю для чего это нужно, но он может что-то такое рассказать, что позволит эту фичу использовать ещё эффективней в будущем как говорится — «век живи — век учись» :)
UFO just landed and posted this here
Слушай, чувак, респект и уважуха за столь подробное разжёвывание темы лямбда-выражений в С++. Очень порадовало, что ты не только рассказал всё более подробно, но и рассказал про подоснову всей этой кухни (это я про функторы). Теперь эти лямбда-выражения в C++ меня реально заинтересовали :) Обязательно теперь поэкспериментирую надосуге…
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
В последнее время наращивание вычислительной мощности процессоров замедлило ход, и развитие компьютерной техники пошло по пути распараллеливания вычислений. Поэтому в моду начнут входить чистые функциональные языки программирования, такие как Haskell к примеру, ибо в них это самое распараллеливание делается крайне легко. Но так как на текущий момент одним из нюансов является не слишком высокое быстродействие программ, написанных на Haskell, в сравнении с их C++-аналогами, скорее всего в будущем появится новая, гибридная методология, которая будет включать как элементы ООП и функционального программирования, так и, возможно, что-то совершенно новое. IMHO :)
Очень часто самое интересное получается как раз на стыке технологий.
Каким образом (анонимные) функторы противоречат ООП?
Если функтор принимает в качестве параметра другой функтор, а возвращает третий — это смотрится несколько странновато и непривычно, хоть, возможно, и не противоречит ООП.
Для C++ — пожалуй.
Последнее время, по-моему, для С++ уже нет ничего странного и необычного.
UFO just landed and posted this here
Суть от этого не меняется.
UFO just landed and posted this here
Если не злоупотреблять размерами лямбд, то ничего не усложняется. А так, в С++ полно мест, где можно очень неплохо на голову себе навесить проблем. Принципиально лямбды ситуацию не ухудшат.
Это не goto, это способ алгоритмической абстракции (здесь в статье хороших примеров нету, но подошло бы объяснение fold/map).

В ООП (которое message passing) такие «костыли» (лол) тоже есть, ибо сами сообщения — объекты первого класса.

Как раз таки *отсутствие* функций/сообщений первого класса приводит к костылям.
По сути, map — это transform, а fold (он же свёртка списка) — это accumulate, если я всё правильно понял. Это, конечно, очень грубо говоря…

Я только недавно начал учить Haskell, поэтому пока что не могу привести хорошие примеры :(
А то, что само ООП в С++ немного костыльное, вас не смущает?
да у меня то же что-то ругается на этом месте
Эм… Дело в том, что это фича из будущего стандарта C++, и сейчас она реализована только в Visual Studio 2010 Beta и отдельных бранчах gcc вроде как.
$ gcc-config -c
x86_64-pc-linux-gnu-4.4.1
получается в последнем gcc эта фича еще не реализована, очень жаль.

P.S. Хотя, с другой стороный, второй листинг скомпилировался без поблем.
Эта фича еще не вошла в trunk проекта gcc, потому что новый стандарт C++ по сути еще не вышел, но в отдельных сборках, я слышал, уже работает.

А второй листинг скомпилировался потому, что это как бы аналог первого листинга, но записанный исключительно средствами текущего стандарта C++.
извиняюсь, туплю ) там же нет никаких лямбд.

А так спасибо, очень интересно, в общем-то как и все новое (:
Учите Haskell ;) — там всё новое…
хах, буквально вчера за него принялся, действительно интересно :)
Статья действительно хорошая. А вот лямбды в c++ конечно выглядят громоздко. По той же причине, я использую замыкания в javascript но не использую анонимных функций т.к. это выглядит не так мило как в Lisp/Haskell/ML и проще объявить их рядышком.
суровая статья, спасибо
у меня вопрос: как все это будет работать без автоматической сборки мусора? я псал на С++ достаточно давно и уже не в теме, но не принесут ли лямбды в С++ лишней головной боли с утечками памяти? и вообще они каким-то образом влияют в этом вопросе или бояться нечего? мне было бы интересно узнать

за статью спасибо, жду продолжений и подобных статей, автор, пиши еще :-)
Ну если фактически компилятором это будет разворачиваться в функтор, то, мне кажется, утечек памяти это за собой не повлечет. В любом ведь случае эти лямбды будут создаваться совсем не динамически.
std::copy( a.begin(), a.end(), std::ostream_iterator( std::cout, " " ) );

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

int elementsInRow = 0;
auto traceLambda = [=] (int _val) mutable
{
        cout << _val << " ";
        if (++elementsInRow % 5 == 0)
        {
                elementsInRow = 0;
                cout << endl;
        }
};

А зачем elementsInRow обнулять если % 5 написано? Можно либо написать if (++elementsInRow == 5) либо убрать обнуление, без изменения смысла
Да, сорри, это у меня гибрид из двух разных версий :)

Без обнуления не пойдет… Мало ли, сколько у нас там элементов. Должно быть вот так:

int elementsInRow = 0;
auto traceLambda = [=] (int _val) mutable
{
        cout << _val << " ";
        if (++elementsInRow == 5)
        {
                elementsInRow = 0;
                cout << endl;
        }
};
Да, my fault. Хотя маловероятно что мы будем обрабатывать коллекцию с 2 миллиардами интов, это же 8 гигов памяти. Или в stl можно будет конструировать бесконечные списки как в haskell?
Насколько я знаю, бесконечных списков не предвидится. А 8 гигов памяти в наше время — не так и много…
Громоздко слишком. Вот в том же ATS (ats-lang.org) это делается проще и практически также эффективно.

Да-да, я понимаю, что это исследовательский язык и все такое, но С++никам следует обратить на него пристальное внимание.
UFO just landed and posted this here
Скорее всего, это просто тренды, не следовать которым — отставать в практической применимости. С++ изначально представлялся конструктором, с помощью которого можно стоить не только дома, но и инструмент, с помощью которого эти дома делаются. Но когда количество самодельного инструмента превысило отметку в 9000, все-таки решили причесать этот зоопарк и ввести наиболее употребимое непосредственно в язык. Временами получается несколько неуклюже (как раз из-за начальной ориентации в перпендикулярном направлении): и синтаксис лямб — не верх изящества.
Только монад и pattern matching'а не хватает)
Не переживайте :) C++ — мультипарадигменный язык… Будут :))) гг
UFO just landed and posted this here
В листинге 13 необходимо явно указывать возвращаемый тип первой лямбды -> void?
как сказал автор статьи — это тип возвразщаемый по умолчанию. Поэтому указывать его явно не обязательно
ну кроме случаев, когда тама есть один retun, который и определяет возвращаемый тип.
Да, -> void можно не указывать, а вот дальше -> function<int (int)> все-таки пришлось указать, потому что компилятор сам не смог вывести тип.
UFO just landed and posted this here
UFO just landed and posted this here
Есть неосвещённое белое пятно.
Что происходит со ссылками на переменные, вышедшие из области видимости?

function<void ()> foo()
{
int init = 0;
return [&init]() { ++init; };
}

Подозреваю, что со ссылкой ничего не произойдёт, после возврата из foo она будет указывать на адрес на стеке и использование результата функции foo() будет разрушать значение в этой ячейке стека.

Или я не прав?
> Есть неосвещённое белое пятно.
Мда, ну и фразу написал…
Grammar nazi негодуе.
Замените это на функторы и всё станет ясно.
Вы сохранили ссылку на переменную, которой после выхода из функции нет. Что в таком случае положено? Не важно, лямбда там или нет, обращение по этой ссылке — undefined behaviour.
Прекрасная статья, снимаю шляпу вместе с волосами перед умением автора доносить мыслю. Отплюсовался где только мог :)
спасибо за статью. тема сисек лямбда функций почти раскрыта
Спасибо. В следующий раз постараюсь донести больше сисек подробностей о фичах нового стандарта…
респект автору. статья очень полезная.
Спасибо, было приятно ознакомиться, пока еще не приходилось читать такого внятного рассказа о лямбдах в C++.
UFO just landed and posted this here
Спасибо большое за ссылку! Почитал. Довольно интересно, но я так и не заставил себя всерьез заняться изучением Objective-C. На первый взгляд замыкания там действительно попроще, чем в C++ :)
UFO just landed and posted this here
Если нужно компилировать только средствами от Apple, то это уже не чистые C/C++ ;)

P.S. Ей-богу, не осилил разобраться в XCode. Мне сказали, что XCode удобно использовать только для Obj-C, но не для C++. Посему с программингом под Mac у меня как-то вообще не сложилось.
UFO just landed and posted this here
Я касательно C++ в последнее время вообще подсел на Qt, поэтому предпочитаю Visual C++ (которому IMHO нет равных) и Qt Creator.

А вообще сейчас пытаюсь переквалифицироваться в Haskell-программера :) Так что до Obj-C я точно не дойду.
UFO just landed and posted this here
Не слышал, честно говоря. Мне продукты Apple нравятся, но я от них не настолько фанатею, чтобы все силы кидать на программинг под них.
а нетипизированные лямбда-функции существуют (в виде шаблонов)?
я же вас не спрашиваю, зачем ввели лямбду, когда спокойно обходилось обычными функторами. вот и вы, пожалуйста, тоже…

ладно, так уж и быть, отвечу на ваш вопрос. без лямбда-шаблонов новшество будет уступать функторам в гибкости.
Если ввели, значит «обходились неспокойно», однако для программистов С++ (не знакомых с функциональным программированием) лямбда-выражения скорее всего будут не более чем синтаксическим сахаром, который иногда весьма удобно использовать. Но Вам же никто не говорит заменять все функторы на лямбды.

А как Вы себе вообще представляете объявление шаблонной лямбды?
А так ли важно, как я их себе представляю? То, что паре программистов с хабра не удалось этот синтаксис себе вообразить, не должно наводить на мысль о невозможности или ненужности. Было бы желание, а синтаксис придумать можно. Да хоть включив объявление параметров шаблона в начало списка параметров функции:

[]...(typename T1, typename T2, int i, T1* pt1, const vector& v) {...}

Но на самом деле мне не нравятся две вещи. Во-первых, синтаксис — недостаточно элегантно для меня, чтобы отдавать ему предпочтение. А во-вторых, вложенные лямбды будут отрицательно сказываться на удобочитаемости кода (впрочем, этот момент мне даже в лиспе не нравился, когда мы его изучали в университете).
Опечатка в последнем параметре шаблонной лямбды, хабраредактор съел параметры вектора из-за угловых скобок. Вектор должен быть инстанциирован типом T2.
После прочтения статьи волосы встали дыбом. C++ такой C++. В C# просто пишешь лямбду и не задумываешься, какой нафиг у переменной захват, mutable/не mutable, что такое анонимный функтор с перегруженным оператором и так далее. Неужели ЭТИМ будет кто-то всерьез пользоваться? Да тут можно таких дров наломать, что потом неделю отлаживать придется.
Программисты на С++ привыкли думать во время работы. Если для Вас это непривычно, то продолжайте C#, незачем терзать себя таким страшным языком, как С++.
Зачем вы так) Я очень люблю C++ (и написал на нем много кода), просто утверждаю, что в языке стало больше на одно место, где можно эпически облажаться начинающим программистам.

Думать это правильно, но ведь зачем-то придумали абстракции, чтобы упростить жизнь нашему брату. Можно писать на ассемблере например, там очень сильно думать надо. Введению auto я очень рад, он избавляет от рутинной работы. Лямбды по идее тоже избавляют от рутинной работы, но… Когда есть с чем сравнивать, становится неловко. Если бы они появились в середине девяностых, они произвели настоящий фурор. Но не в наше время.
И да, появился новый вопрос на собеседовании, соберется ли код
int main{[](){}()}

:)
Тьфу, то есть
int main(){[](){}();}

Статься содержит ошибку. Так не разрешается

[&, x, &y] // захват всех переменных по ссылке, кроме x…

Если указан захват по умолчанию &, то все явные захваты должны быть по значению. То есть &y в данном списке не допускается.

И наоборот, если указан захват по умолчанию =, то все явные захваты должны быть по ссылке.

Изначально я предположил, что в 2009 году черновая версия спецификации не содержала такого ограничения, но несложно проверить, что это ограничение присутствовало с самого начала.

Sign up to leave a comment.

Articles

Change theme settings