What is "lambda" in c#? - Page 1
Forum section: electronics / general

author: eti
author_rank: Super Contributor
timestamp: April 18, 2022, 01:05:22 am
content: I am puzzled. I know not a vast amount about C#, apart from loving the syntax etc.Could someone explain what a "lambda" function is, for a beginner? I have highlighted it in red... and if you could treat me as if I know a moderate amount about programming, but not a vast amount... thankspublic void wait(int milliseconds){var timer1 = new System.Windows.Forms.Timer();if (milliseconds == 0 || milliseconds < 0) return;// Console.WriteLine("start wait timer");timer1.Interval = milliseconds;timer1.Enabled = true;timer1.Start();timer1.Tick += (s, e)=>{timer1.Enabled = false;timer1.Stop();// Console.WriteLine("stop wait timer");};while (timer1.Enabled){Application.DoEvents();}}

author: IanB
author_rank: Super Contributor
timestamp: April 18, 2022, 01:21:58 am
content: I'm not sure how we could explain it better than you could find out by searching online for documentation and examples?In short, it is a local and anonymous definition of a function.In other words, it is a function that can only be referenced in the place you define it. It has no name, and cannot be seen by any other part of the code.The example you showed is somewhat incomplete, since it claims to take "s" and "e" as inputs, and do something with them, but in this particular case it does not use them.In this particular example, the "+=" is overloaded, and it is adding an event handler to the list of event handlers maintained by timer1.Tick. Every time the Tick event happens, it will call the event handlers that have been added to it.This is a slightly odd overloading of "+=", since normally "+=" will do an arithmetic addition, rather than appending something (an event handling delegate function) to a list.

author: chickenHeadKnob
author_rank: Super Contributor
timestamp: April 18, 2022, 01:36:49 am
content: Lambda (anonymous) functions are not immediately an intuitively useful construct until you consider a language that can call functions through function pointers. Then you can entertain ideas like storing a table of function pointers. Say a table representing a state machine. And with lambda functions you then don't need to invent a whole bunch of silly arbitrarily unique names just to label and define those functions.

author: eti
author_rank: Super Contributor
timestamp: April 18, 2022, 01:39:18 am
content: Quote from: IanB on April 18, 2022, 01:21:58 amIt does use them, as when I removed them, the code doesn't work. Btw the "=>" you see is not an equality test as you imply, I think, but instead it is some form of character arrangement which tells the compiler "this is a lambda"... but I could be wrong. It is not a standard thing, such as "== blah" or "+= blah" - yeah, that caught me out too. I Googled and Googled, looked on YouTube - sorta got the gist, but the final layer of mental mist still hasn't cleared.

author: IanB
author_rank: Super Contributor
timestamp: April 18, 2022, 02:02:16 am
content: Quote from: eti on April 18, 2022, 01:39:18 amIt does expect them to be there, because they are the expected input parameters of such an event handler. However, it doesn't use them, as you can see there are no references to them in the body of the event handler.QuoteI didn't say anything about equality tests. But you are correct, the "=>" indicates the definition of a lambda function.I said the "+=" text after timer1.Tick indicates that the lambda function should be appended to the list of event handlers for the timer1.Tick event.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 18, 2022, 05:19:00 am
content: I'm not familiar with C# but the syntax looks reasonably similar to the JS case of which I am familiar. Simply, "(a...) => {}" returns a function, taking parameter list (a...) and executing statements {}.It's a handy shorthand; often you want a quick one-liner callback function, like, well for some event handlers as above for example; but also for specifying how to sort an array for example. In that case, the sort() function passes two elements at a time to your lambda, which returns some representation of the ordering of those elements (like for numeric or string arguments,(a, b) => return a < b;).You can of course use a function object definition (at least in JS, but C# probably has something similar?..), it's just syntactic sugar for "function(a, b) {statements...}".The basic idea, of function pointers/references, is extremely old; plain old C has them (the declaration of which looks... bizarre, but, it is what it is), though obviously not anonymous functions and lambdas. (Kind of odd actually, in that most types are generalized in that sort of way -- you can have anonymous inner types/unions/structs, but not functions.) It's just a nice feature to add.That's the basics. The harder stuff comes when using variables outside of local scope. You can reference variables in the parent function, to varying degrees of success/effect depending on language. Usually, copies are made either when declaring the lambda, or as the function drops out of scope, so that the values can still be used by the lambda without mucking up the stack or whatever (since, for example in C, non-static local function variables are stored on the stack, and therefore a naive lambda would point at now-out-of-scope stack that could be anything).Tim

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 19, 2022, 05:44:44 pm
content: While functions as a first-class object are an interesting feature, I personally do no think they make much sense in a non-functional programming language.Note that I'm specifically talking about functions as *first-class objects*. Functions pointers are different. "Function pointers" are obviously extremely useful in non-functional languages, even if not without potential pitfalls, but function pointers are not functions."Lambda functions" are supposed to be first-class objects, so I do find them oddballs in non-functional languages, and indeed they are. Not surprising they got added to C++ which is an "all you can eat buffet", and some other languages that try to shove as many paradigms (with none of them implemented properly) as they can.While they may look "cute" at first sight in a non-functional language, I personally do not buy they're a good addition.Anonymous functions may seem practical, but they often lead to harder to read code, and more code duplication.The example of a comparison function for sorting is a common one. Thing is, a separate function usually makes the intent clearer, because the name is supposed to help describing the purpose. It's like with variables. That may look so productive not to have to come up with names, but just think of a program full of anonymous variables. Yeah, no. Another point is reusability. Even for a simple comparison function, it happens frequently that you will reuse the same function in different contexts in some code. Defining it once is much better than duplicating the code with a lambda every time you need it. Ugh. So in practice, I see little use of lambdas outside of pure functional languages, and a lot of downsides.One potential benefit would be performance - compilers can inline lambda functions more efficiently. But does that make a lot of difference and is it worth the trouble? I doubt it.Just my opinion of course.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 19, 2022, 06:06:22 pm
content: Also as first class objects, it makes sense in a fully dynamic language; functional languages are fairly obvious, and JS is interpreted primarily (then JIT'd as needed) so functions can be created just out of thin air at any time and it's no problem. In a compiled language, that code already exists somewhere, statically, and then is assigned as function pointers; it's in the binary, just unnamed (or rather, given some automatic mangled name by the compiler) and the syntax / semantics are source level only, so, of varying utility, and may be more or less helpful to ease of creation / readability / maintainability as you say.I wouldn't say it's something that should be avoided, but like all things, it should be used appropriately, sparingly even.Tim

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 21, 2022, 07:58:33 pm
content: Quote from: T3sl4co1l on April 19, 2022, 06:06:22 pmWell, nope. Not necessarily, and as I mentioned out of fairness, this is even one point in favor of them in compiled languages if I can give them one.Compilers have the opportunity to efficiently inline lambda functions wherever they are used as if they were just expressions in a macro (without the pitfall of macros), so in that case, that can be more efficient than a function compiled separately and just called from its pointer.Some smart compilers can do the same with function pointers if said function is within the same compilation unit and the function itself can easily be statically derived from its pointer (which is not always the case depending on the code), but there's no guarantee. With lambda functions, there's a lot more opportunity for optimization.But as I said, whether this is worth it compared to the downsides...Typical code (say C++) using lambdas that I've read pretty much looks like horrible and unmaintainable gibberish.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 21, 2022, 11:21:12 pm
content: Yeah fine, it might not be a function pointer in the finished object/binary, thanks to optimization; I should say, semantically you can't tell the difference.Tim

author: Fred27
author_rank: Unknown
timestamp: April 22, 2022, 09:44:22 am
content: One thing Microsoft do really well is provide accurate and complete documentation which is kept up to date (unlike for instance Amazon AWS). A quick search will bring lots of good info.

author: gf
author_rank: Super Contributor
timestamp: April 22, 2022, 08:58:12 pm
content: Quote from: SiliconWizard on April 19, 2022, 05:44:44 pmOne difference to a regular function is that a lambda has closure semantics, i.e. it can capture variables from its enclosing lexical scope. For a sort compare function this is usually not needed. For other kinds of callback functions it can sometimes be useful to have a "referencing environment" attached to the function.