top | item 25763375

(no title)

qppo | 5 years ago

Type inference is great and undeserving of the "bah humbug" type comments. Not a fan of it in function return types but that's easy to avoid in code review or linting (both of which you need plenty in C).

The closure proposal is much more interesting. I skimmed the discussion and it points out many of the benefits and some syntax proposals, but I'm wondering about memory management.

In C++ a lambda may not be convertible to a function pointer if the captured context is non zero sized, and if the captured context is larger than the size of a pointer it must use some kind of dynamic allocation. C++ has scoped destructors, making implementation of that relatively straightforward (free the context when the lambda goes out of scope), but what would C require? Defer statements? Require a free() without matching call to malloc?

Closures in C are still possible using void* as a user context, which is common both for closure semantics in libraries as well as implementing closures in languages transpired to or interpreted in C. The memory management is explicit, the types remain explicit (except for the closed over context), albeit a bit verbose.

As much as I love functions as types and programming with them I'm confused how this is a positive feature for C, which lacks some of the semantics that other languages have making closures sensible.

discuss

order

MauranKilom|5 years ago

> In C++ a lambda may not be convertible to a function pointer if the captured context is non zero sized, and if the captured context is larger than the size of a pointer it must use some kind of dynamic allocation

You are mixing things up here. A lambda will never require memory allocation, regardless of its size: https://godbolt.org/z/Mebn4h

std::function can't get around memory allocation for sufficiently large functor objects, but that is a matter of how libraries implement type erasure for functors and has nothing to do with the lambda expressions of the core language.

jcranmer|5 years ago

So this proposal retains the C++ feature of not allowing you to do anything with the captured context. Semantically, it's as if you created the captured variables as new function-local variables when you initialized the function call, and the wording makes it UB to modify the captured variables via a pointer.

Where the capture context lives in memory and how it is allocated and deallocated is not precisely specified by the specification, but there specification does permit it to be handled via C++-style scoped destruction. That C has no way for you to manually write this code does not preclude implementations from using that logic internally, especially since most C compilers are also C++ compilers and handling C lambdas as identically to C++ lambdas as possible would have some benefits.