• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
doeme

Anonymous/lamda functions: curse or blessing?

19 posts in this topic

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 [url="http://msdn.microsoft.com/en-us/library/bb531253.aspx"]http://msdn.microsof...y/bb531253.aspx[/url])"

* [2] [url="http://thedailywtf.com/Articles/Soft_Coding.aspx"]http://thedailywtf.c...oft_Coding.aspx[/url]
0

Share this post


Link to post
Share on other sites
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
-1

Share this post


Link to post
Share on other sites
#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 [i]policy[/i] 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 [i]that[/i].


L. Spiro
1

Share this post


Link to post
Share on other sites
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).

0

Share this post


Link to post
Share on other sites
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.
0

Share this post


Link to post
Share on other sites
Lambdas and asynchronous code go so well together and make that sort of code more readable and maintainable in my opinion.
2

Share this post


Link to post
Share on other sites
[quote name='doeme' timestamp='1321524239' post='4884909']
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".
[/quote]

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.

[quote]
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 :)
2

Share this post


Link to post
Share on other sites
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.

[quote name='doeme' timestamp='1321517834' post='4884882']
Do they make the code unreadable and hard to maintain?
[/quote]

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?

[quote]
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.

[quote]
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.

[quote]
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.

[quote]
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.
0

Share this post


Link to post
Share on other sites
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.
1

Share this post


Link to post
Share on other sites
[quote name='jwezorek' timestamp='1321657765' post='4885443']Although I do find it a little sad that boost::bind, et. al., have basically been deprecated now -- that stuff was amazing.[/quote]
If it's deprecated why was it added to C++11 then?
0

Share this post


Link to post
Share on other sites
All C++0x lambdas are is a nice syntax for function objects (delegates) -- literally.

I had to back port a bunch of code that was written using early support for lambdas because the static analysis tool I was using on the code didn't yet support them. The translation was mechanical; I could have trained a monkey to do it. My understanding is that this is essentially the same as what the compiler does -- so there's no worries about them doing scary stuff behind your back. The code is a lot more readable with lambdas because a) the body of the function is right where you need it, and b) you loose all the function-object overhead you'd need otherwise -- a minimal function object is probably around a dozen lines of code, vs many minimal lambdas that fit in just a portion of a single line.

Think about it this way -- How many times have you *not* used function objects in your design when you wanted to because the overhead was a pain to deal with? Or, how many hours have you wasted writing, refactoring and debugging function objects where you did use them? These are basically the problems that C++0x lambdas solve -- They make the barrier to entry for writing robust, re-usable (composible) code incredibly low. This is probably why your co-worker is scared, function objects are painful, therefore something that makes them easier must be evil. Fortunately, the exact opposite is true.

As JWezorek points out, they make the C++ Standard Library work "like its supposed to" -- The Standard Library is built around this kind of compositional ability (using compile-time polymorphism implemented through template parameters -- things like comparison objects and custom allocators), and if lambda support had been around earlier the standard library would no doubt have used them instead.

Another thing is that they go hand-in-hand with asynchronous programming -- which is a huge and growing deal. Its great for UIs, great for long-running processes, IO, remote calls and much more. Asynchronous programming is going to be unavoidable from here on out, you best get ready for it.

Lambdas, 'auto' and move semantics are the three big things that will change the way we write C++ in the coming years. A lot of the template stuff (variadic templates) is arguably more game-changing, but its going to be a while before support for that is wide-spread, while lambdas, 'auto' and move semantics are here today pretty broadly, and furthermore template programming (and template meta-programming, more specifically) are still quite a dark art for many.

[EDIT: Thanks Zahlman for fixing the formatting. Sticking with the non-rich editor from now on; its more trouble than its worth.]
1

Share this post


Link to post
Share on other sites
[color=#CCCCCC][size=2]All C++0x lambdas are is a nice syntax for function objects (delegates) -- literally.[/size][/color]
[color=#CCCCCC][size=2]
[/size][/color]
[color=#CCCCCC][size=2]I had to back port a bunch of code that was written using early support for lambdas because the static analysis tool I was using on the code didn't yet support them. The translation was mechanical; I could have trained a monkey to do it. My understanding is that this is essentially the same as what the compiler does -- so there's no worries about them doing scary stuff behind your back. The code is a lot more readable with lambdas because a) the body of the function is right where you need it, and b) you loose all the function-object overhead you'd need otherwise -- a minimal function object is probably around a dozen lines of code, vs many minimal lambdas that fit in just a portion of a single line.[/size][/color]
[color=#CCCCCC][size=2]
[/size][/color]
[color=#CCCCCC][size=2]Think about it this way -- How many times have you *not* used function objects in your design when you wanted to because the overhead was a pain to deal with? Or, how many hours have you wasted writing, refactoring and debugging function objects where you did use them? These are basically the problems that C++0x lambdas solve -- They make the barrier to entry for writing robust, re-usable (composible) code incredibly low. This is probably why your co-worker is scared, function objects are painful, therefore something that makes them easier must be evil. Fortunately, the exact opposite is true.[/size][/color]
[color=#CCCCCC][size=2]
[/size][/color]
[color=#CCCCCC][size=2]As JWezorek points out, they make the C++ Standard Library work "like its supposed to" -- The Standard Library is built around this kind of compositional ability (using compile-time polymorphism implemented through template parameters -- things like comparison objects and custom allocators), and if lambda support had been around earlier the standard library would no doubt have used them instead.[/size][/color]<br style="color: rgb(204, 204, 204); font-size: 13px; line-height: 16px; text-align: left; background-color: rgb(55, 55, 55); "><br style="color: rgb(204, 204, 204); font-size: 13px; line-height: 16px; text-align: left; background-color: rgb(55, 55, 55); ">[color=#CCCCCC][size=2][left]Another thing is that they go hand-in-hand with asynchronous programming -- which is a huge and growing deal. Its great for UIs, great for long-running processes, IO, remote calls and much more. Asynchronous programming is going to be unavoidable from here on out, you best get ready for it.[/left][/size][/color]<br style="color: rgb(204, 204, 204); font-size: 13px; line-height: 16px; text-align: left; background-color: rgb(55, 55, 55); "><br style="color: rgb(204, 204, 204); font-size: 13px; line-height: 16px; text-align: left; background-color: rgb(55, 55, 55); ">[color=#CCCCCC][size=2][left]Lambdas, 'auto' and move semantics are the three big things that will change the way we write C++ in the coming years. A lot of the template stuff (variadic templates) is arguably more game-changing, but its going to be a while before support for that is wide-spread, while lambdas, 'auto' and move semantics are here today pretty broadly, and furthermore template programming (and template meta-programming, more specifically) are still quite a dark art for many.[/left][/size][/color]
0

Share this post


Link to post
Forgive the formatting and wall of text. I don't understand how they adopted third-party software that specializes in this sort of thing, yet is so freaking broken. Trying to fix it only makes it worse.
0

Share this post


Link to post
Share on other sites
At work, the standard interview questions cover lambdas and closures.

If a prospective gameplay programmer can't answer these questions, they're probably not going to get the job, because they've just shown they're not familiar with modern programming. 'nuff said [img]http://public.gamedev.net/public/style_emoticons/default/tongue.gif[/img]

A prospective systems programmer might be more likely to get away with not knowing this stuff, because they're expected to be working in C++ (pre-0x) most of the time ([i]though, they should still known the concept of a functor etc[/i]).

Regarding their use in C++, you'll find that most code-bases already use something analogous to them (functors etc). All this addition does is make the syntax for this existing technique nicer.

[edit] @Ravyne, You've got to kill it with fire: edit post->full editor->select all->remove formatting->insert all your newlines again...
0

Share this post


Link to post
Share on other sites
I've been using them quite a bit lately.

Their use requires getting up a bit of a learning curve and training your eye to recognize a new syntax. I'm not too old, I can do that, so can you and your cow orkers.

As long as their bodies are kept fairly short, they are scads better than the more traditional functor found elsewhere in the code: this is the code locality advantage others have mentioned.

After considerable experimentation, I determined that using a lambda with std::for_each is almost never worth it. A simple range-for or a for-loop with auto variables is clearer in both intent and typography. The flip side is lambdas are ideal for use as one-off predicates in other algorithms.

They are a useful tool and like most tools, have their ideal use and potential for abuse. Do not let timorous cow orkers fool you into thinking change is bad because change is bad. Find better cow orkers instead.
1

Share this post


Link to post
Share on other sites
[quote name='Bregma' timestamp='1321673738' post='4885511']Their use requires getting up a bit of a learning curve and training your eye to recognize a new syntax. I'm not too old, I can do that, so can you and your coworkers.[/quote]100% agreed. I have been looking forward to use them since C++0x was announced.

BTW, I currently assimilate them to "inlined function pointers". Any thoughts on that? Edited by Krohm
0

Share this post


Link to post
Share on other sites
[quote name='Bregma' timestamp='1321673738' post='4885511']
After considerable experimentation, I determined that using a lambda with std::for_each is almost never worth it. A simple range-for or a for-loop with auto variables is clearer in both intent and typography. The flip side is lambdas are ideal for use as one-off predicates in other algorithms.
[/quote]

I think using a lambda as the body for for_each is still clearer than a plain for-loop - the normal for-loop body can break, return, and change the loop variable or size of the collection you're iterating over (ouch!). I think you're suggesting using range-for in that case, but unfortunately for me msvc doesn't yet support it.

Maybe I'm just weird though - I'm starting to prefer find_if with a lambda to a raw while loop, for example.

In a fit of over-enthusiam for lambdas, I experimented with using a lazily evaluated integer range (i.e. boost::counting_iterator) with for_each and a lambda, instead of plain for-loop. Interestingly, it seemed to be only 10% slower than the plain for-loop, which only made a difference in my inner-most loops. I was also playing with concurrancy libraries though, so that 10% may not be generally applicable [img]http://public.gamedev.net/public/style_emoticons/default/tongue.gif[/img]
0

Share this post


Link to post
Share on other sites
[quote name='Ravyne' timestamp='1321660363' post='4885457']
Forgive the formatting and wall of text. I don't understand how they adopted third-party software that specializes in this sort of thing, yet is so freaking broken. Trying to fix it only makes it worse.
[/quote]

It's HTML5. You know, the future of the web, the computing, the holy grail that replaced Flash and other buggy technologies and crappy native apps.The technology which just works in every browser on every device for everything imaginable. People have ported Linux to it and the new era of rich web apps awaits us.
0

Share this post


Link to post
Share on other sites
No one has mentioned what it's like when it comes to debugging code that uses lamdas. What are other's experiences there?
0

Share this post


Link to post
Share on other sites
I've so far only had to single step code which is a lambda for a std::for_each (or a function like it) at which point it does what you expect; simply step into the code much like it is a normal function/scope with no sillyness.

It might be different if you bind a lambda to a std::function and step in but as I've had no reason to debug that yet I couldn't say.

(All experiance with VS2010)
0

Share this post


Link to post
Share on other sites
[quote name='Ravyne' timestamp='1321660363' post='4885457']
Forgive the formatting and wall of text. I don't understand how they adopted third-party software that specializes in this sort of thing, yet is so freaking broken. Trying to fix it only makes it worse.
[/quote]

I think I fixed it. My suggestion: go to "My Settings" and uncheck "Enable visual (RTE) editor?", and kick it old-school.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0