LINQ
is higher-order functions - Ruby `map` is 'Enumerable.Select`, Ruby `select` is `Enumerable.Where` etc.
The special syntax is really just syntactic sugar on top of all this that makes things a little bit more readable for complex queries because e.g. you don't have to repeat computed variables every time after binding it once in the chain. Consider:
from x in xs
where x.IsFoo
let y = Frob(x)
where y.IsBar
let z = Frob(y)
where z.IsBaz
order by x, y descending, z
select z;
If you were to rewrite this with explicit method calls and lambdas, it becomes something like:
xs.Where(x => x.IsFoo)
.Select(x => (x: x, y: Frob(x)) }
.Where(xy => xy.y.IsBar)
.Select(xy => (x: xy.x, y: xy.y, z: Frob(xy.y)))
.Where(xyz => xyz.z.IsBaz)
.OrderBy(xyz => xyz.x)
.ThenByDescending(xyz => xyz.y)
.ThenBy(xyz => xyz.z)
.Select(xyz => xyz.z)
Note how it needs to weave `x` and `y` through all the Select/Where calls so that they can be used for ordering in the end here, whereas with syntactic sugar the scope of `let` extends to the remainder of the expression (although under the hood it still does roughly the same thing as the handwritten code).
The special syntax is really just syntactic sugar on top of all this that makes things a little bit more readable for complex queries because e.g. you don't have to repeat computed variables every time after binding it once in the chain. Consider:
If you were to rewrite this with explicit method calls and lambdas, it becomes something like: Note how it needs to weave `x` and `y` through all the Select/Where calls so that they can be used for ordering in the end here, whereas with syntactic sugar the scope of `let` extends to the remainder of the expression (although under the hood it still does roughly the same thing as the handwritten code).