Hacker News new | comments | show | ask | jobs | submit login

Context always matters. I use lambdas sparingly in my applications, except for one major area: user interfaces.

I can't begin to stress what a huge timesaver it is being able to bind a button's callback to a quick lambda instead of having to bind a callback to an std::function, add the function to the class header, and then put the actual button-click code somewhere else in the project in a separate function ... and then repeat that process for a large UI with hundreds of widgets.

It's not even the initial extra typing, it's having all the code right where it's most relevant instead of scattered around everywhere and having to name all of these callback functions.

Yeah I think this is the real win - the examples in the paper don't really cover any of the real reasons why someone would use functional programming. The places that I've used C++ lambdas a lot are callback-heavy code, i.e. things with a lot of asynchronous I/O, multi-threading, etc.

While I don't doubt the validity of the argument that it takes longer for a programmer to write correct lambda code in C++ (I have been using them since C++11 was released and still forget the capture list syntax sometime), it's not much more than an academic exercise to take some iterator-based code and replace it with higher-order function calls. It's unfortunate that all the tasks seem to be based around doing that though. I do think it is still reasonable to do this in C++11 once you know how - with -O1 turned on you can get basically the same code spit out using std::transform, std::accumulate, std::for_each, et al, as you would using a for loop.

It's also unfortunate to note that, at least in g++ and clang, there is still significant advantage to using lambdas over std::function and std::bind. Lambdas typically end up being faster in both compile-time and run-time, and end up generating less code. For these reasons I've found myself using them a lot more, especially anywhere I would have done some type of currying. This I do miss somewhat, but it's still leaps and bounds ahead of something I would have written in C++03.

> It's also unfortunate to note that, at least in g++ and clang, there is still significant advantage to using lambdas over std::function and std::bind.

I have to say, std::bind is just a travesty. It's so difficult to bind a member function pointer that takes multiple arguments to an std::function.

I wrote my own so that you can do this with just: function<void (int, int)> f = {&Class::func, &object};

Source is here: http://hastebin.com/raw/kobudabasa

In doing so, it becomes clear there's basically two ways to implement this idea:

1. you allocate heap space to perform type erasure. This results in a pointer indirection plus a virtual function call worth of added overhead. Along with tremendous costs to allocate and destroy the function objects.

2. you store a big chunk of raw memory inside the function<> class, and cast it as necessary to a pointer. This is actually what I did prior to C++11 and lambdas. It was tricky because the size of member function pointers is undefined. Having a vtable makes them larger. So for that I made a complex dummy class to pull its sizeof info.

Option 2 is definitely a good bit faster (at least for constructing/copying/reassigning/destructing them), but you're really butting up against undefined behavior and abusing the language. And capturing lambdas would be even more challenging.

But even with that, yeah, you can't ever really beat concepts that are native to the language like lambdas and virtual functions themselves. Compilers can get really clever and inline things in a way that's exceedingly unlikely to ever occur with std::function, no matter how you implement it.

I've also written my own "version" of function but intentionally lightweight, for an embedded project: https://github.com/ambrop72/aprinter/blob/master/aprinter/ba...

Callback<void(int, int)> f = APRINTER_CB_OBJFUNC(&ThisClass::function, this);

One magic thing is that the macro is just a value, it figures out the type itself.

There's zero memory allocation. The Callback class just contains a function pointer and a void pointer. So you can't bind argument values other than the object pointer, but I have no need for that.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact