Live data from Hacker News

Lambda expression comparison between C++11, C++14 and C++17

maitesin.github.io

51–60 of 87 posts

Re: Lambda expression comparison between C++11, C++14 and C++17

#51

Earlier quoted context omitted.

The explicit capture list is only necessary in C++ because memory ownership and lifetimes are managed by the programmer in C++. Compare that to a garbage-collected language like Scheme or C#: when the implementation can figure out where memory needs to be freed and ensures you can't use-after-free, it frees the programmer from thinking about ownership (but not necessarily lifetimes: you can still wind up with memory…

It was enough of a problem in Scala to warrant this though http://docs.scala-lang.org/sips/pending/spores.html

Spores seem like an interesting solution. The language designer in me has a distaste for it, though :p

For case 1 (capture of mutable references), an explicit copy operator might be better (as in, "I want whatever value this variable is bound to, rather than the storage location") (or even vice versa, where value is the default and there's an operator for location). In a way, spores accomplish this by forcing you to do the copy manually -- but then programmers have to always remember to use the extra syntax, and they need to do it for every captured variable. I'm not quite happy with even this solution, and it may be possible to come up with something even better. Concurrency is always a can o' worms :)

For case 2 (capture of implicit "this"), I'd argue that if (a) the compiler is smart enough to know that "helper" is implicitly "this.helper" and (b) that "this" will be captured by the closure, then (c) the compiler is also smart enough to create an implicit binding for "helper" and capture that instead. This would lead to less-surprising behavior, and intentional capture of "this" could still be done via explicit access. Another option is to, rather than treating "this" as being in an enclosing scope, treat it as though it were an implicit argument to the method (albeit a covariant one). This avoids capture altogether.

Re: Lambda expression comparison between C++11, C++14 and C++17

#52
post #47

Nice. I am a bit confused -- before c++17 it is impossible to capture this by copy; is it possible to capture other objects by copy? seems like it is?

Yes, it is. Just write:

  [a](...){ ... }
and the variable "a" will be captured by copy.

Re: Lambda expression comparison between C++11, C++14 and C++17

#55

There is another interesting feature in C++17 for lambdas: Possibility to cast a lambda to a function pointer. It will become possible to store a lambda as a struct/member that could bind to "this" (like in Javascript).

I assume this is only for stateless lambdas, that have not captured anything? Because otherwise a function pointer would not be enough, right?

Currently, any stateless lambda can decompose into a function pointer and be passed to any function that expects a function pointer, right?

Are you saying that ++17 has augmented this, and if so can you provide more details or a reference (or an example) as I'm quite curious to know more.

Re: Lambda expression comparison between C++11, C++14 and C++17

#56

Nice overview. Just a small correction: the smallest possible lambda is []{} and not [](){} as stated in the article. The parameter list is optional.

>The parameter list is optional.

To avoid confusion, only an empty parameter list is optional. You can't omit the parameter list if you take args, unlike lambda shortcuts in languages like clojure which allow you to implicitly refer to arguments inside the body using a universal variable name, and therefore omit the parameter list for all lambdas. That possibility does not exist in c++.

Re: Lambda expression comparison between C++11, C++14 and C++17

#57
I love lambdas, but a lot of commenters are throwing around the word "closure" here, and c++ lambdas are definitely not closures. You can capture outside variables by value or by reference, but that value can expire before the lambda runs if the reference no longer exists; in which case, you are in trouble. Unlike a true closure (as in lisp or other languages), where the closed-over value stays around.

If we talk only about c++ capture lists by value (i.e. [=]), then you could make a case for a more appropriate use of the word "closure" but since many lambdas do more than this, I think the distinction is necessary.

However, even in by-value captures, if you are capturing a pointer by value, the issue remains. So, really it is not a good idea to think of lambdas as closures in the functional sense typically used in other languages.

Re: Lambda expression comparison between C++11, C++14 and C++17

#58
post #37
post #10

Taking a concept such as a lambda function and making it look this ugly...this is why I hate C++. I wish I wasn't forced to program it every day.

What would you propose as the syntax?

I honestly would have much preferred they had a keyword so that it kinda matched the rest of the language. It feels a bit tacked on and hard to parse.

Something like:

lambda(arguments):capture list {...}

Just seems way more clear. Looks more like a function or a class (and a lambda is sort of an in-between kind of thing anyway)

Re: Lambda expression comparison between C++11, C++14 and C++17

#59
post #39
post #37

Earlier quoted context omitted.

What would you propose as the syntax?

Apple extended C with block closures years ago. int b = 0; ^(int a) { return a*b; } The declaration for lambda variables is almost identical to function pointers, just with a ^ instead of a *, so there's nothing to learn (or unlearn, like C++ forces you to). The ^ looks like a lambda, and historically the lambda of lambda calculus actually was a caret accent over the variable. The argument list can be elided.

And this is why C++ couldn't use this notation, as they didn't want to break compability with this extension of Apple's.

Re: Lambda expression comparison between C++11, C++14 and C++17

#60
post #13

Earlier quoted context omitted.

How is it ugly? The capture list is a necessary complexity in a language with manual memory management.

The syntax is not the prettiest, but it is legible once you understand what [](){} means. In C#, there is no such thing, but there is a part of me that wishes we had such a thing. I like the ability explicitly state what variables are being captured.

> I like the ability explicitly state what variables are being captured.

Why? You state what variables are being captured by just using them in the lambda body.

Post reply on HN