Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Closures and precise control over memory allocation doesn't play very well together.

How so? In C++ a lambda is just a regular type that does not allocate any memory by itself. You have in fact precise control over how/where a lambda is allocated.





True, but once a capture needs to survive the parent function scope you'll need to store it somewhere, either via a std::function object which has opaque rules on whether a heap allocation happens or via your own std::function implementation where you define the heap allocation rules but then will have to face discussions about why you're rewriting the stdlib ;)

Any C implementation of capturing lambdas has the same problem of course, that's why the whole idea doesn't really fit into the C language IMHO.


I did a version with explicit capture objects for fun: https://github.com/fuhsnn/c-extensions#extended-capture

Basically, with each capturing lambda, a context type _Ctxof(fn) is created that users can then declare on stack or on heap themselves.


Interesting! Can you tell me about your experience? How does it compare to the versions in N3654? (where this idea comes from) https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3654.pdf

- Non-capturing isn't that much simpler to implement for the front-end, because they still need to distinguish between a file-scope name or a shadowing local in parent function. And once you have the code to do that distinction, it's not that far away from implementing captures.

- From implementor point of view I just don't like the idea of a new category of function qualifiers, so I used "_Wideof(int(void))" over "int(void) _Wide", and "int fn({...}, void)" over "int fn(void) _Closure/_Capture(...)".

- During prototype scope of the inner function, parameters may have VM type that reference from parent's local scope, so the capturing (or not) effectively start at prototype scope, earlier than C++'s model. My syntax has capture clause right before parameters so it is somewhat manage-able in one pass; for function qualifier syntax the parser probably need to either delay semantic checking the VMs or skip ahead to find _Closure/_Capture before processing the parameters.

- Both N3654-example6 and N3694-4.4.6 implicitly create capture context on stack then provide reference to it (N3654 with &_Closure(), N3694 with inner function's name). My version is lower level in that only the type of capture context (_Ctxof(fn)) is implicitly created, users then call a helper (modeled after va_start) to initialize the context object. I believe it also reduces surprises from by-value captures, since users clearly see where they initialize a context object relative to local variable changes.

- Sans syntax, N3654's "specified argument" is pretty close to my implementation, just need to change the source of context pointer from r10 to the argument in function prologue.

- I implemented wide function pointers as generalized "function pointers with context pointer pushed in r10", so it's also possible to make wide pointers from regular functions, they'll just be called with an extra nullptr in r10. I think it's more flexible this way.

What I did was mostly "the compiler will need these anyways" so should be adaptable to whatever WG14 settled on, or if I ever want to implement C++11 lambda.


Thanks! What I do not quite understand is the need for a capture clause that lists the captured variables. As a user, I do not want to list my captures. As a code reviewer I certainly do not want value capture that create a modifiable copy with the same name, or any ambiguity on whether something is a copy or not. I just want to access my variables. So what is really the point here?

Regarding "also possible to make wide pointers from regular functions", this exactly the reason why I like the qualifer version: The usual conversion rules for qualifiers would allow this conversion implicitly, while back-conversion is not allowed (or only with cast).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: