Nested Functions

I miss nested functions and don't know why they fell out of favor. Nested functions usually inherit the variable scope of the "parent" function. They are useful for factoring out repetition of code in a function to a sub-function that is otherwise too specific to be reusable in another context. Passing gajillion parameters the current way is annoying and unnecessarily verbosity.

If a sub-function will likely only be used with a given function, then it does not need to pass around the entire scope through parameters. Something more akin to BASIC's "GOSUB" is sufficient within a smaller scope. Parameters are generally still possible where needed or helpful in sub-functions, but the rest of the scope is inherited from parent function. (The most-local scope has precedence over same-named object in parent routine.)

I generally classify nested functions as being "static" and "dynamic". Static functions are hard-coded to a given parent function and can only inherit scope from that one parent. Pascal is an example of such[1]. It achieves this by allowing one to physically nest functions in the code. The nested function automatically has scope access to the parent's variables (and those above it in the hierarchy).

Dynamic nesting is when a function can inherit the scope from any caller. It is usually found in "scriptish" languages. One drawback found in such languages is that one cannot turn off this feature. I think it would be better to have scope inheritance off by default, but selectable by a key-word of some sort. (As in CommonLisp.)

(Php allegedly has "nested function" ability, but the variable scope is not nested, defeating the purpose.)

--top

The Rel implementation of TutorialDee (see RelProject) has nested functions, lightweight relvars (think "tables"), and a generally procedural-ish nature that you might like. Anyway, don't recent versions of Perl support nested functions with user-specified dynamic or lexical (static) scope?

[All of the most commonly used scripting languages (PerlLanguage, PythonLanguage, RubyLanguage, PhpLanguage, JavaScript) support nested functions with LexicalScoping - it's a less convenient feature in some languages than in others, however. In JS and Python, it's pretty much frictionless: Functions declared inside functions are local to the surrounding function and automatically have access to all bindings in the surrounding scope. It's more difficult in Perl, Ruby, and PHP because these languages treat a "normal" function declaration as global, even if it's inside another function. One must therefore explicitly use anonymous function syntax to get local nested functions, like so:]

# perl
sub outer {
my ($localvar) = @_;
my $inner = sub {
my ($innerparameter) = @_;
return operationAppliedTo($localvar, $innerparameter);
};
return $inner->("something");
}

# ruby def outer localvar inner = lambda {|innerparameter| operationAppliedTo localvar, innerparameter } inner.call "something" # or inner["something"] end

// php function outer($localvar) { $inner = function(innerparameter) use (&$localvar) { // the 'use' clause is needed to capture the variable from the surrounding scope return operationAppliedTo($localvar, $innerparameter); } return $inner("something"); }

[However, the above techniques are typically rare in production code, since they require "weird" syntax. The equivalents in Python and JS are practically ubiquitous due to their relative convenience. -DavidMcLean?]

Other developers would shoot me if I used such a "different" approach.

[Indeed. In RubyLanguage, the right approach to such things is to implement the would-be-nested functions as methods on some new class (a MethodObject, if no more applicable class comes to mind for the particular case). This is a fairly clean and practical solution primarily because Ruby is the only language of those mentioned that does not suffer from SelfDotSyndrome. Perl and PHP unfortunately lack a clean, consistent way to spread functionality over inner functions; PHP has it worst, as it demands "use" on anonymous functions and exhibits SelfDotSyndrome. -DavidMcLean?]


[1] By trying to be a one-pass compiler, Pascal imposes an annoying ordering of function definitions. This is not something to keep. I'll live with the speed penalty of two-pass because it's usually best human-wise to define sub-functions below main/higher functions.


CategorySyntax, CategoryLanguageFeature, CategoryScope


EditText of this page (last edited July 21, 2014) or FindPage with title or text search