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

I took issue with this because it's a conventional wisdom, and does a fair bit of damage.

Single-caller functions attract other callers over time, gain backwards-incompatible features, and result in regressions.



This is one reason I like nested functions. They’re not available to the surrounding scope so they don’t succumb to these weaknesses, while also allowing you to organize your very long function internally by task. I use ‘em in Python all the time.

It’s a bummer that more languages don’t support them, though you can get there with lambdas too, sometimes at the cost of more syntax.


Go has closure functions; great feature.

One of the (few) things I like about Javascript is the ability to define a closure anywhere in the containing function, so it appears in the order of operations:

  function f() {
    setTimeout(fDing, 2000);
    g();
    function fDing() {
      ...
    }
  }


Disclaimer: I have no Golang programming experience.

I am curious with this approach though...you're nesting behavior and/or logic, doesn't this further obscure the meaning of the code and contribute more to the need to jump around the source in order to figure it out?


Go has anonymous functions too.

The Go Programming Language book (Kernighan and Donovan) has some examples of them.


Now write a unit test for

    function fDing() {
      ...
    }
Honestly with modern JS I am not sure this feature is that great. Looks more like a code smell these days imo.

Edit: Formatting


Now write a unit test for the inline block of code within the longer function which would have become the nested function???

You write the test (where any is needed) for the outer function.

Edit: the start of the discussion was about using nested functions to decompose what otherwise would have been “unpartitioned” long functions. Such blocks of code nested within a long function would not be possible to unit test, either.

Unit tests, rather than integration tests, are usually bogus, anyway, though.


You write unit tests for units of code. A function with nested functions inside of it is a single unit of code; that's essentially what those functions being nested, and hence not directly invokable from the outside, indicates.


Make private functions that are only visible to the current module. Then write your unit tests directly in that same module, next to the functions, so they can access them even when the rest of the world cannot. Of course, this requires sensible language support.


Hierarchy vs list. I don’t want a list (of subroutines). I want a tree of self contained routines. Only your containing routine uses you. Which “private“ routines use which? (I know the IDE will tell me about this routine, and that routine, but I don’t want to have to ask)

Your employer doesn’t want you testing getters, anyway, but rather features. Unit test fanatics need to stop.

I guess unit tests were useful for C++, when it was constantly crashing everything :-(

C++ and its legacy need to ride off into the sunset, already.


A bit of our “heritage” in programming destroyed by the C family of programming languages

Pascal, like Algol, had nested subroutines for decomposing longer operations without leaking the details.

Nested functions is one of the things I like about JavaScript as well.


C has static functions for decomposinglo ger operations without leaking the details.

For better or for worse, taking advantage of that forces you to keep source files fairly short and cohesive in functionality.


You are still leaking the details of the function that is the sole caller of those other functions. It's not leaking across translation unit boundary, but it's not the only one that matters.


ML derived languages, Julia, D and C# support them.


GNU C supports nested functions as an extension. I use them for the exact reasons you mention.


That extension results in executable stack memory, which is going to be a non-starter for many developers.


I believe that that only happens if you pass a nested function as a function pointer. Then gcc emits a trampoline.

If you just call it from the enclosing function it's fine.


Yeah, agreed. I do this in Rust a lot too, and I picked it up while writing a lot of Python.


C# has inner named functions.




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

Search: