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

> People using Ada, Pascal (Delphi), JavaScript, or functional languages should also declare types and functions as locally as possible.

My own personal approach in JavaScript is to avoid defining functions in a nested manner unless I explicitly want to capture a value from the enclosing scope.

This is probably due to an outdated mental model I had where it was shown in performance profiling that a function would be redefined every time the enclosing function was called. I doubt this is how any reasonable modern JavaScript interpreter works although I haven't kept up. Since the introduction of arrow functions (a long time ago now in relative terms) their prolific use has probably lead to deep optimizations that render this old mental model completely useless.

But old habits dies hard I guess and now I keep any named function that does not capture local variables at a file/module scope.

A lot of the other notes are interesting and very nit-picky in the "technically correct is the best kind of correct" way that older engineers eat up. I feel the general tone of carefulness that the NASA rules is trying to communicate to be very good and I would support most of them in the context that they are enforced.



For most languages, the inner function body when first defined is parsed/compiled once, with the unbound free variables collected in a list. At the next calling of the function definition, the compiled function body is reused and only the free variables are bounded to the variables in the outer environment (closure). It's quite efficient. Depending on the implementation, it could just be a two-element struct pointing to the compiled function body and to the outer environment. Or it could be a small call thunk embedding the setup of the variable bindings and the jump to the address of the function body.


FYI inline functions are reused these days. So are object / array literals within a certain size.

In some cases inline functions (if they fall within V8 optimisations) can be re-used more cheaply than the overhead of non-inline alternatives like binding or currying


I use gcc's nested functions a fair amount. Because it reduces cutting pasting and makes the code much easier to understand.

I use variable argument macro's to implement debug print functions for debugging. And I just leave them in the code as a form of documentation. Looking at the debug print statements tells you a lot of about what the code is doing.


Unfortunately, as useful as they really are, GCC's nested functions are usually done via trampolines, which means an executable stack. That's not really a safe thing, when dealing with critical systems, like NASA regularly do.


This isn't the case for Ada on GCC, so the support is there, it just hasn't been extended to C:

> The use of trampolines requires an executable stack, which is a security risk. To avoid this problem, GCC also supports another strategy: using descriptors for nested functions. Under this model, taking the address of a nested function results in a pointer to a non-executable function descriptor object. Initializing the static chain from the descriptor is handled at indirect call sites.

> On some targets, including HPPA and IA-64, function descriptors may be mandated by the ABI or be otherwise handled in a target-specific way by the back end in its code generation strategy for indirect calls. GCC also provides its own generic descriptor implementation to support the -fno-trampolines option. In this case runtime detection of function descriptors at indirect call sites relies on descriptor pointers being tagged with a bit that is never set in bare function addresses. Since GCC’s generic function descriptors are not ABI-compliant, this option is typically used only on a per-language basis (notably by Ada) or when it can otherwise be applied to the whole program.

> For languages other than Ada, the -ftrampolines and -fno-trampolines options currently have no effect, and trampolines are always generated on platforms that need them for nested functions.

From: https://gcc.gnu.org/onlinedocs/gccint/Trampolines.html


Aye, "usually" up there was the implication.

You can actually do it in C, too! It just requires setting up a few macros, and getting it right requires a fairly decent understanding of the underlying hardware. (via TARGET_CUSTOM_FUNCTION_DESCRIPTORS).


This only a problem if you pass the nested function as a function pointer and you have a machine with a no execute stack.

The processors I program for don't have no execute stacks so the use of a trampoline is of no consequence.

Also my memory was that no execute stacks were heralded as the solution to stack smashing attacks. No execute stacks problem solved. And turned out if you're vulnerable to stack smashing no execute stacks won't save you.

So I feel we threw out something good, nested functions for some cargo cult security. And since no one uses them the reactionary luddites on WG14 are free to hope they go away.


Yeah, in JavaScript I'll pretty much only write nested functions to use them as scope control, and usually I don't intend for that function to be callable elsewhere. Otherwise, I prefer writing functions that are as "pure" as possible, even if that means having to pass in many parameters each call.


He is the odd




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: