Anonymous/lamda functions: curse or blessing?

Started by
18 comments, last by Zahlman 12 years, 5 months ago
As C++0x includes support for lambda-functions[1] this sparked some discussion at my workplace about if they are a 'do' or a 'dont'. Of course this is a pretty complex matter and the pros and cons depend on a lot of circumstances, but I would like to hear some opinions about the use of anonymous functions.

Do they make the code unreadable and hard to maintain?
Are they the perfect way to create spaghetti-code? (one of our developers actually thinks they are as bad as a goto)
Are they a problem with code-stabilty?
Is the use of lambda-functions the perfect way to soft-code things? [2]

What are your experiences and opinions with them?

* [1] Using Microsofts definition of 'lambda-function'
"A lambda expression is a function or subroutine without a name that can be used wherever a delegate is valid. Lambda expressions can be functions or subroutines and can be single-line or multi-line. You can pass values from the current scope to a lambda expression. (from http://msdn.microsof...y/bb531253.aspx)"

* [2] http://thedailywtf.c...oft_Coding.aspx
Advertisement
I didn't use any lambda feature in C++. (It's too new)
But I used a lot closure (a little same as lambda) in ActionScript.

Here are my opinions,

1, Treat lambda as expression rather than function.
That implies that lambda should be quite simple (1~several, maybe 5 lines of code).
If it goes complicated, it worths a well named function or functor object.
With this rule, lambda won't break readability because every one can read what it does in its simple code.

2, I don't know what other usage of lambda, but I only used it (AS closure) as callbacks.

My 2 cents

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.

#2: Spaghetti is up to so much more than just a feature of a language. My code won't become spaghetti because I used lambda functions. It would be because I have poor organizational skills.
If some at your office are that way, perhaps they should have some restrictions in place, and not just in regards to lambda.

#3: I don't see how they could make your code unstable.

#1: Hard to read? Contrarily I find it handy having the function definition right there so I can see how the short stub of delegate code is working.
Since I only use them for very short segments of code, such as with sort functions, they don't clutter up my functions much.
Additionally, they really tend not to need maintaining. I only use them for very specific purposes that, once implemented, have a very very low chance of ever needing to change in the future.


I wouldn't worry about these issues unless you actually start to see them happening.
And if you do, you may want to consider other things besides just the use of lambda functions as contributors to that mess.
If you do find lambdas to be the problem, focus on what caused that problem and revise your policy on when and where you use them.
That doesn't mean ban them, but make a note that they are not suitable for that type of task and just don't use them for that.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

They are great, probably the best feature in C++0x.

Makes code more readable since it can be placed where it is used.

Also easier to read since less boilerplate nonsense(C++03 functors).

I quite like the way to add small code snippets with lambda expressions.

What really sparked the discussion was that the syntax of the lambda-indroducer ([], [=], [&]) and the definition of return types with -> may look confusing at first sight. This is as well the main argument to making them "unreadable".

Concerning code stability this was more an issue in conjunction with the signal/slot mechanism, where we registered a lambda-expression to a signal and then deleted the object around it which left the expression dangling around.
Lambdas and asynchronous code go so well together and make that sort of code more readable and maintainable in my opinion.

What really sparked the discussion was that the syntax of the lambda-indroducer ([], [=], [&]) and the definition of return types with -> may look confusing at first sight. This is as well the main argument to making them "unreadable".


Meh, I'd consider that more a case of 'being new' rather than 'unreadable'. I dare say the first time your co-workers looked at C or C++ they felt it was 'unreadable' but soon got use to it. Personally I took to it right away and for places where it makes sense I find combining it with the various C++ algorthims it makes code considerably more readable.


Concerning code stability this was more an issue in conjunction with the signal/slot mechanism, where we registered a lambda-expression to a signal and then deleted the object around it which left the expression dangling around.
[/quote]

While a problem it's not a problem unique to lambda functions; anything where you can pass a reference/pointer around in your code can hit that problem too.

As for the original questions;

1) Once you grok the syntax I'd say no. If anything they make code easier to maintain as the functionality is right there in front of you rather than shuffled off into some function or functor object requiring a scroll about to see what is going on.

2) Again; no. You can hardly 'spagetti code' thing as the defintions are right in front of you. You can't go jumping about the place and is probably less spagetti inducing than a normal function.

3) No more so than any other feature and as I'd argue their locality to usage for things like registering call backs you'll gain better code stability. Problems such as 'we registered a call back and now it is left dangling!' can be done just as well with a pointer.

4) Scripting languages and config files are perfect for soft coding. Lambda's bring nothing new to the table here.


Lambdas + std::function + std::bind allow for some pretty cool things to be done much easier; granted, I don't use these at work due to the need to be compatible with 3 consoles and the PC, but at home I'm all VS2010's and lambda'd up :)
I don't know much about C++0x's implementation, so I'm going to assume it's reasonable to other languages' and not broken.


Do they make the code unreadable and hard to maintain?


They can. C++0x's syntax is a bit verbose which might be problematic, but it's got to be better than functors or a mush of binding hoops right?


Are they the perfect way to create spaghetti-code? (one of our developers actually thinks they are as bad as a goto)
[/quote]

They can easily be abused, but they tend not to just slide naturally toward abuse.


Are they a problem with code-stabilty?
[/quote]

No. Localizing little expressions into lambdas as opposed to functors or helper functions like you have to do now can only help code stability from a bit-rot standpoint.


Is the use of lambda-functions the perfect way to soft-code things? [2]
[/quote]

Enh. When you use lambdas it's because you're passing them somewhere. If what consumes them is uncoupled/configurable enough to take a lambda in the first place, it's easier to un-hard/soft-code the problem bits.


What are your experiences and opinions with them?
[/quote]

Without them, it becomes difficult to write properly generic code. Any sort of case where you need variable behavior becomes awkward to use, either at the call site or in maintenance when you're trying to figure out what this magic enum means you should do...

I like the code-locality of them. I don't have to skip through files to find out exactly what this or that helper function does. The predicate (or other plugged behavior) is right there.

The auto-magical scope closure behavior I've found is increasingly important to create 'lazy' behavior that detects changes to a variable without the headaches of alternatives like polling or event proliferation or improper knowledge of observers.


In general, this sort of thing is good and will become more good and vital as functional and parallel computing continue their inroads into general purpose programming.
C++ lambdas make the STL work the way it was always supposed to work. Without them you had to bend over backwards to use STL algorithms unless you didn't mind your code sprinkled with many one or two line free or static functions. I mean don't get me wrong, you could do a lot with boost::bind and so forth it's just that it required a lot more thought than [&](const Foo& foo) -> Bar { return foo.bar(); } etc .

Although I do find it a little sad that boost::bind, et. al., have basically been deprecated now -- that stuff was amazing.
Although I do find it a little sad that boost::bind, et. al., have basically been deprecated now -- that stuff was amazing.

If it's deprecated why was it added to C++11 then?

This topic is closed to new replies.

Advertisement