Hacker News new | past | comments | ask | show | jobs | submit login

Great survey but why on earth does there need to be a book about lambdas in C++???



I just wish there was nested functions instead of these lambda classes.


I sympathize with you here. I kind of like the lambda syntax for simple cases in C++, but the complex cases look painful to me, and based on everything else in C++, I predict there are many special cases to remember.

However, if you just want a more conventional syntax for nested functions, you can almost get what you want by placing a static method inside of a local class, and it's available in older versions of C++ too:

    #include <stdio.h>

    int main() {

        struct foo {
            static void bar() {
                printf("nested\n");
            }
        };

        foo::bar();

        return 0;
    }
If you want it to "close" over your local variables, you'll probably need to actually instantiate an instance of the local class and use a non-static method. Doing this, the capture lists in lambdas almost start to make sense.


Clever. If you let the nesting function have static variables they can be referenced from the nested function too, but actually using lambdas would of course be more clear in practice.

The only feature of lambdas that a proper nested function would miss is the "copy capture".


> The only feature of lambdas that a proper nested function would miss is the "copy capture".

Yeah, reference by default would fit with what people probably expect from other languages, but without a garbage collector (or similar) that's only valid for downward passed functions. Copying allows your nested function to escape the lifetime of the calling function, which might require some other/additional syntax.


eh.... having to deal with Python's stupid lambdas, C++ lambdas are far superior. You can always do:

auto func = [](...){....}

for nested funcs


Yeah, using lambdas as nested functions is pretty common.


Ye but I would just want the possibility for the simpler syntax like the GCC extension for C where you can do:

    typedef void fp_t();
    void foo(fp_t fp)
    {
        fp();
    }

    int square(int num) {

        void square_nested() 
        {
            num = num * num;
        }

        foo(square_nested);

        return num;
    }
That would work as long as you don't need copy capture.


I really don't see how that is so much better than the alternative that it would warrant a language change:

  int square(int num) {
    auto nested = [&num](){ 
       num *= num; 
    };
    nested(num);
    return num;
  }


Slight mistake: should be

    auto nested = [](int& num){
(or switch calling nested to have no params)


The HN C++ compiler ;-)


I agree, given the fact that lambdas are already here.


what would nested functions bring you that lambdas don't ?


A slightly saner syntax, compared to:

  const auto iAmANestedFun = [stuff](stuff) -> stuff { ... }
Particularly, if we could assume that nested functions automatically and properly capture the arguments to the parent function.


Not sure I like implicit capture more than explicit capture but there's [=] if you need it. Also, the return value as the article mentions is optional, so most lambdas look like

    const auto nestedfunc = [=](a,b) { /* */ };
Which isn't that much different to me than

    { /* some scope */
        function nestedfunc(a,b) { /* */ }
    }
const and auto are needed but because it's C++. Beyond that, you have an equals sign which is needed here but [=] which is three characters. Again, small differences, not sure why it looks that much worse.


Now that we know lambdas they are fine, but to answer the question "why is there a book" in the beginning of the thread, it is more or less because it is not as obvious as gcc's c extension.


What is so cryptic that there needs to be a separate syntax change?

    auto triple = [](auto x){ return 3 * x; };


Ye well nothing when we have already are to lambdas.


No need to spell each variable nor give a return type:

   auto f = [&](...) { ... };
That covers the majority of cases.


> Particularly, if we could assume that nested functions automatically and properly capture the arguments to the parent function.

well, how would you do that ?


By having the compiler generate the equivalent of [&args...], where args are names of arguments in the parent function's header.


why [&args...] and not [args...] ? do you really want to capture by reference when you're setting a lambda as a callback ? (likewise in the other direction - tons of arguments for every default, already debated ad nauseam)


And why specifically args instead of all locals?


You mean like this? https://godbolt.org/z/jvG3hY


I don’t know any other language with lambdas which requires me to spell out explicitly which variables it should close over... so you tell me how Java, Scala, Clojure, Kotlin, Python, JavaScript, Rust, Go, C# and tens of others managed this clearly impossible feat of engineering.


> I don’t know any other language with lambdas which requires me to spell out explicitly which variables it should close over

PHP closures have to specify which variables they close over, and whether it's done by-val or by-ref [0].

Nowadays there's also a shorthand single-expression-closure syntax that closes implicitly and by value [1].

[0]: https://www.php.net/manual/en/functions.anonymous.php#exampl...

[1]: https://www.php.net/manual/en/functions.arrow.php


Forced heap allocation and GC of course that would be unacceptable in C++.

IIRC Rust uses capture modifiers similar to C++.


Rust is not really the same as C++ here, you get "the compiler infers how to capture things" as the default behavior, and "take everything by value", which happens with the "move" keyword. We've found that these two cases cover the vast, vast, vast majority of usage, and so C++-style specific capture modifiers aren't necessary. You can emulate C++ style stuff by taking references outside of the closure and using move to capture only the reference.


Hypothetical nested functions could just use the regular function syntax. Lambdas can be quite a different beast.


gcc has had those (as a non-standard C extension) for a while. Too bad it never made it into the standard.

https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html#Nes...


Too bad it would be really nice for sort() etc.


Why would it make a difference? You can pass an anonymous function with two auto arguments as the comparison to sort.


It wouldn't pollute the file scope namespace. You can define it in eye sight of the sort call, steal variables from the nesting functions stack etc.


... but how's that different of what we have today ?

    std::sort(vec.begin(), vec.end(), 
              [] (const auto& lhs, const auto& rhs) { 
      return lhs.whatever < rhs.whatever;
    });
or

    auto sort_by_whatever = [] (const auto& lhs, const auto& rhs) { 
      return lhs.whatever < rhs.whatever;
    };
    std::sort(vec.begin(), vec.end(), sort_by_whatever);


Sorry was refering to C in that comment with no lambdas, with the GCC extension.




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: