I've never used this gcc extension; but I'll try to explain according to my interpretation of the link you gave.
As far as I understand the documentation, the crucial difference is that those nested functions don't allow you to build what a functional programmer would understand under "closure" -- those nested functions can't be used outside their definition context, because the stack variables they use get lost after the outside function exits.
In Haskell, when I do the following:
const x = \y -> x
foo = const 2 -- remember or "close over" 2
bar = foo 1 -- now, bar == 2
You see that when applying const
to 2
, the argument 2
gets "saved" by the closure which we have called foo
. Afterwards, in bar
, 2
can be recalled and returned -- because it still is remembered in foo
. However, in C:
typedef int (*int_to_int_fn)(int);
int_to_int_fn constant(int x)
{
int constant_impl(int y) { return x; }
return constant_impl;
}
int main()
{
int_to_int_fn foo = constant(2);
int bar = foo(1);
}
That probably doesn't even compile, but if it would, it would go against basic expectations we have of a C function: the x
in foo
, made out of the argument of constant
, would need to stay somewhere (probably not on the stack!), until some time later foo
gets called. That's not how stuff primitively works -- and C is primitive, in this sense (we'd probably need to allocate something on the heap, copy stuff, clean it up later, worry about references/values, etc.).
Some enlightenment can probably be achieved by looking at the C++11 lambda syntax. There, constant_impl
could be written somewhere along this:
auto constant_impl = [x](int y){ return x; }
The [x]
part there is exactly the place where we tell the compiler "please, remember x for me!".