0

The current trend seems to be to use lambda type function in languages that can take that syntax. Is this just a trendy thing or is actually more efficient? eg in javascript, you can get stuff like

var x = ((aa,bb) => {
    ....
    aa((xyz) => {...}
    }).then((aa, bb) => {
    ...
    }).doit

Is it actually more efficient for the javascript interpreter to execute code like this or is it more efficient for the coder to define separate functions and call them. This is also happening a lot in C#.

6
  • 2
    Possible duplicate of Is micro-optimisation important when coding?
    – gnat
    Commented Nov 10, 2016 at 6:04
  • Your question is not about inline functions Commented Nov 10, 2016 at 6:16
  • It is not about C++ type inline functions - it is about nameless functions which are written inline. They were called inline functions in the late 60s until C++ grabbed the term and made it it something specific
    – cup
    Commented Nov 10, 2016 at 6:40
  • 1
    The question reads like a rant from someone who hasn't used inline functions enough to understand their uses and thinks everyone is an idiot for using them. If that's not the case, I recommend that you edit the question to tone down the ranty-ness or else this is going to end up being closed. Commented Nov 10, 2016 at 6:57
  • 2
    Removed rantiness - I'm just wondering whether people actually find it easier to code/read with nameless function statements or whether it is just coded like that for the sake of efficiency.
    – cup
    Commented Nov 10, 2016 at 7:06

3 Answers 3

5

This isn't directly an answer about the efficiency of anonymous functions, but more about the coding style, since I get the impression that this is what the OP really cares about. (Especially pre-edit, the question seemed to be more "I think this style is unreadable, so people must be doing it for efficiency, am I right?")

There is a balance to be struck in all code between verbosity and conciseness. They are opposites, but neither is all good; they both have disadvantages.

Code that is too verbose is hard to read because reading code takes time, time in which you forget what you previously read. In addition, verbose code tends to contain additional information (such as the name of a non-anonymous function) that competes for space in your short-term memory with other information. Finally, it can introduce non-locality, e.g. if you introduce another function that you now have to go look for in order to understand the code.

Code that is too concise is hard to read because you have to keep to many details in your head without having a moniker to refer them by, and because lots of concise code clumps up, making it easier to lose your place in the code while reading. And it requires you to understand all the details of the code, whereas a well-named extracted function can often be treated as a black box.

Somewhere in the middle is the point of maximum readability.

Here's an example that just involves mathematical calculations. Let's say I have a function that calculates something simple, like celsius to fahrenheit conversion:

function celsiusToFahrenheit(celsius) {
  return celsius * (9.0/5.0) + 32;
}

Clear and simple. There's a scaling factor and an offset. Some purists might argue that these should be named constants, but I don't see the point; the function is a one-liner and the purpose of these numbers is obvious, and they're not going to change.

However, I could write it more verbosely:

function celsiusToFahrenheit(celsius) {
  let scaledCelsius = celsius * (9.0/5.0);
  return scaledCelsius + 32;
}

Here I took an intermediate result of the calculation and assigned it a name. I shifted more towards verbosity. Did it improve readability? You now have more code to read, and I had to invent an additional name which you have to remember while reading the code. I'd say readability got worse.

Here's a different example. This formula calculates an approximation of radio signal pathloss from a transmitter antenna to a point in space, tuneable with a bunch of user-specified coefficients. This is a simplification of the real formula.

function pathloss(heightAntenna, heightDevice, distance, frequency, coefficients) {
  // formula uses log scale
  frequency = log10(frequency);
  heightAntenna = log10(heightAntenna);
  distance = log10(distance * 0.001);
  return
    (coefficients.A0 + coefficients.A1 * frequency - coefficients.A2 * heightAntenna) -
    ((coefficients.a0 * frequency - coefficients.a1) * heightDevice -
    coefficients.a2 * frequency + coefficients.a3) +
    coefficients.C0 * pow(frequency - coefficients.C1, 2) - coefficients.C2 +
    (coefficients.B0 - coefficients.B1 * frequency) * distance;
}

I think you'll agree that this is completely unreadable. Here, splitting it up in parts really helps.

function pathloss(heightAntenna, heightDevice, distance, frequency, coefficients) {
  // formula uses log scale
  frequency = log10(frequency);
  heightAntenna = log10(heightAntenna);
  distance = log10(distance * 0.001);
  // names are somewhat weird, that's the way they're written in the
  // reference book this is based on
  let a = (coefficients.a0 * frequency - coefficients.a1) * heightDevice -
    coefficients.a2 * frequency + coefficients.a3;
  let A = (coefficients.A0 + coefficients.A1 * frequency -
           coefficients.A2 * heightAntenna) - a;
  let C = coefficients.C0 * pow(frequency - coefficients.C1, 2) - coefficients.C2;
  let B = (coefficients.B0 - coefficients.B1 * frequency) * distance;
  return A + C + B;
}

This is still mathematically challenging, but at least it's broken up into chunks, making it much easier to keep track of which parts are added to which, something that required careful tracking of parentheses in the original version.

Anonymous functions are subject to the same trade-off. Using them improves locality. Overusing them (especially nesting them) makes program flow hard to track. It's up to you to find a balance.

7
  • 2
    "I had to invent an additional name" – That, really, is the important point. Names are expensive. As Phil Karlton said: "There are two hard things in computer science: cache invalidation and naming things". Now, if naming things is hard, this means that things which have names must be important … otherwise we wouldn't bother naming them, right? Inventing a name for something that doesn't deserve one, thus, will artificially inflate its importance, and thus make the reader wonder, why this particular thing is so important when in fact it isn't. tl;dr +1 from me :-D Commented Nov 10, 2016 at 10:25
  • If the name is actually part of the ubiquitous language of the domain I'd make it explicit. If scaledCelcius is common to the domain of temperature conversion (which I do not know) then I'd say it's better to declare the extra variable. I'd even say that 32 also is a magical constant here... wouldn't that be a FREEZING_POINT_OFFSET? Names may be expensive, but the lack of a name is even more expensive in most scenarios, unless the name is totally misleading.
    – plalx
    Commented Nov 10, 2016 at 13:58
  • Then again, there is probably no point in making a fixed well-known formula self-explanatory as it's never ever have to be maintained unless bugged.
    – plalx
    Commented Nov 10, 2016 at 14:03
  • @plalx In my opinion, the "no magical constants" rule is applied over-eagerly by many programmers. I generally try to make my functions so small instead that the constants become self-explanatory. Commented Nov 10, 2016 at 16:50
  • @SebastianRedl A constant can never be made self-explanatory, unless it's a well-known constant. In this specific case the conversion formula is well-known, but if this specific algorithm was specific to the domain of company ABC there would be no way of knowing what these numbers mean by goggling the formula. I also get the point that overly verbose code may not be benefical, but in my experience it's much more common not being verbose enough and I never had a scenario where verbosity made understanding the code harder.
    – plalx
    Commented Nov 10, 2016 at 20:14
6

Anonymous (unnamed) functions are as efficient as named functions. However, nested functions have a slight overhead if they refer to local variables of an enclosing function (such nested functions are called “closures”). The most efficient way to implement this involves one additional pointer indirection for each non-local variable access. This is equivalent to the cost of accessing an instance member / field of an object. It is therefore never more efficient to replace an anonymous function with an object that provides the same functionality through a method.

The only notable drawback of anonymous functions is debuggability – a stack trace cannot refer to the name of the anonymous function since it doesn't have one. If debuggability is more important than keeping related code closely together, extracting the anonymous function may be sensible.

Also, nested functions cannot be tested directly, independently of named/unnamed or closure status of the nested function. If the nested function has individual meaning (and isn't just part of the ordinary control flow – you wouldn't test the body of a for-loop individually), then extracting the nested function to make it testable may be sensible.

But those points have to be weighed on a case-by-case basis. Since nested functions are an integral part of JavaScript and C#, it is not reasonable or even possible to go without them.

3

No, it is typically less efficient.

When you use an inline function, you end up creating a function object. The construction of that object will typically take up some resources. In fact, there is an optimization sometimes applied to javascript to move the inline functions out when we can prove that would be equivalent.

The benefit is to avoid writing one-off functions all the time, let's compare:

function foo() {
   let males = _.filter(people, (person) => person.male);
}

function is_male(person) {
     return person.male;
}

function foo() {
     let males = _.filter(people, is_male);
}

The inline function syntax is useful, because it lets me filter easily over any criteria I want. Otherwise, I'd have to write out a seperate function every single time I used filter.

Of course, some people probably take this too far. Sometimes calling a named function is clearer then writing an inline function, especially if the logic gets complicated. But properly used, it can aide readability (at least, once you've gotten use to it)

1
  • I see two functions being created, one anonymous and one named. Why is anonymous less efficient? Commented Nov 10, 2016 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.