8

I've been trying figure out why lambda expressions don't feel intuitive to me yet. I suspect part of it may be because when I skim code, I sometimes internally translate it to my native language for my own clarity. For example:

endDate.Value = someNullableDate ?? (object)DBNull.Value;
// I could read as:
set endDate to someNullableDate or, if null, to (object)dbNull

An example from another language:

for(int count = 0; count >= 42; count++) {
    cout << "Count is " << count << endl;
}
// May read as:
from an integer "count" as zero to 42 inclusive, display "Count is " and then the integer.

So how would one read the lambda expression in:

var myList = new List<String>(/* various string values */);
var foo = myList.Select(s => s.Trim()).ToList(); //?
Charles Burns
  • 10,310
  • 7
  • 64
  • 81
  • 1
    possible duplicate of [How do I pronounce "=>" as used in lambda expressions in .Net](http://stackoverflow.com/questions/274022/how-do-i-pronounce-as-used-in-lambda-expressions-in-net) – BrunoLM Jun 20 '11 at 14:58
  • 1
    read each element in myList, trim the value, and store the new list as 'foo' – asawyer Jun 20 '11 at 14:58

7 Answers7

11

I would read this as:

Select each item individually from myList into a variable s, using s, apply a Trim() on it and once done with all items in myList, convert the whole thing to a list.

Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162
  • "once done" - not. `While doing so` collect them into a list for future reference (see [Lazy/Deferred Evaluation](http://msdn.microsoft.com/en-us/library/9k7k7cf0(v=vs.90).aspx)) – sehe Jun 20 '11 at 15:21
  • ToList() only executes after the projection to IEnumerable though right? The projection occurs during the Select statement and then "once done", the items are all Enumerated through the use of ToList(). Or do you mean something else? – Jamie Dixon Jun 20 '11 at 15:34
  • nope; 'ToList() only **completes** after the projection bla...'; Subtle but true difference. Your version implies two enumerations (which would not work well with some enumerables, or enumerators that don't support Reset() or enumerators that are costly like [`Directory.EnumerateFiles Method`](http://msdn.microsoft.com/en-us/library/system.io.directory.enumeratefiles.aspx)) – sehe Jun 20 '11 at 15:41
  • As far as I know I'm only implying one enumeration which occurs during ToList(). Are you saying that ToList() works during the operation of Select? If so, I wasn't aware of this. – Jamie Dixon Jun 20 '11 at 16:15
  • 2
    indeed. Or, rather it is the other way around. C# [`iterator blocks` (think: `yield`)](http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx) result in what is technically known as a co-procedure: really (parts of) the Select get executed once every iteration of ToList()'s enumerator loop. This holds no matter how complicated the iterator block is, indeed even if it isn't finite. Step through a handwritten for-each loop for a lazy enumerable once with a debugger and you'll see how that actually works! – sehe Jun 20 '11 at 17:15
4

Given that LINQ generally only works with IEnumerable objects, you could read s => as 'for each s in the IEnumerable'.

Update: Revisiting this answer over 5 years on, I am deeply unsatisfied with it. Personally, nowadays I find myself considering it as "maps to" or I've seen "such that" which is also pertinent depending on the circumstance.

Digbyswift
  • 10,310
  • 4
  • 38
  • 66
  • for each seems to apply very nicely in this scenario. Could you elaborate on how you would apply the 'maps to' or 'such that' concept in this scenario? – rdg515 Apr 06 '20 at 13:10
3

The first few times, you'll need to break the full expression to bits and convert them to syntax you are familiar with and eventually you'll get familiar with lambda.

In this snippet,

var foo = myList.Select(s => s.Trim()).ToList();

Select() does projection operation similar to that in sql.

s => s.Trim() can be converted to

string SomeMethod(string input)
{
    return input.Trim();
}

and the last ToList() is an extension method that converts IEnumerable<T> to List<T>.

Bala R
  • 107,317
  • 23
  • 199
  • 210
3

I don't read it in English. It's kind of like speaking a foreign language. Once you really get it, you don't go back and forth to your native language to use it.

While I could translate it to English, the attempt seems to mangle the meaning of the untranslated code. (i.e. "Set foo to a List of the trimmed values in myList.")

John Fisher
  • 22,355
  • 2
  • 39
  • 64
2

something along the lines of:

from myList, trim each string "s" and put it into a new list

Bas
  • 26,772
  • 8
  • 53
  • 86
1

For every String item in myList, perform a Trim() on the item, then return the results as a list.

See the documents on Enumerable.Select. It's essentially a built-in foreach with the ability to return the result after it's been processed.

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
0

I wrote the original question as I was learning C# and now find LINQ very intuitive.

I read my original code:

var foo = myList.Select(s => s.Trim()).ToList(); //?

As:

For each string "s" in myList, trim "s", then ToList() the results.

Today I would not use LINQ for this task. Fundamentally it is a query language (the Q in LINQ), and is not necessarily the most efficient choice for modifying a list. Were I to still choose LINQ, I would use it's .ForEach() method.

Charles Burns
  • 10,310
  • 7
  • 64
  • 81