If you have ever used Pascal and similar languages you will soon
see the value of it. It allows careful control of scope, for
functions, variables and other things (eg. CONST in Pascal).
Scope is not the only, nor to my mind the more interesting,
consequence of nesting functions.
Nested functions (in any proper implementation) capture their
ancestors' closures. That has potentially complex and interesting
consequences for program design.
Consider a recursive visitor-pattern function, for example - let's
say a function that iterates depth-first over a binary tree and calls
a delegate function at each node.
At the top level we have something like:
void Visit(struct tree *tree, void (*visitor)(struct tree *))
{
if (tree)
{
visitor(tree);
Visit(tree->left, visitor);
Visit(tree->right, visitor);
}
}
But if we have nested functions, we can push the recursion down a
level and hoist the visitor-function parameter out of it:
void Visit(struct tree *tree, void (*visitor)(struct tree *))
{
void Visit_r(struct tree *tree)
{
if (tree)
{
visitor(tree);
Visit(tree->left);
Visit(tree->right);
}
}
Visit_r(tree);
}
That saves us a parameter per recursive call, because Visit_r's
environment includes the current values of Visit's parameters and
local variables.
Now, in the actual implementation, there will likely be a hidden
parameter (as Chuck mentioned) for the static chain, unless the
implementation uses a display or some more esoteric mechanism. But
the nested-function representation is still clearer, as it only
explicitly passes the changing parameter, and if there are multiple
parameters that can be eliminated this way, there's a net savings.
However, C doesn't have nested functions, and adding them is a major
change to the language. There are plenty of programming languages
that *do* have nested functions, so people who want them have that
option. When I want a language with lots of expressive- ness, I use
OCaml or something like that. When I want to work in a tightly-
specified language with minimal black-box magic, I use C.