4 ms·
What are the advantages of this over using higher order functions? In Ruby I can do list.map { }.select { } …. That feels more natural (doesn’t require special
by meisel 1y ago
What are the advantages of this over using higher order functions? In Ruby I can do list.map { }.select { } …. That feels more natural (doesn’t require special language support), has a very rich set of functions (group_by, chunk_while, etc.), and is something the user can extend with their own methods (if they don’t mind monkeypatching)
- int_19h 1y agoLINQ 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).
- deleted 1y ago[deleted]
- sumibi 1y agoI tend to use the query syntax a lot for this exact reason. It would be even better if it supported exposing pattern matching variables and null safety annotations from where clauses to the following operations but I guess it's hard to translate it to methods. Something like this: from x in xs where x is { Y: { } y } select y.z Another feature I'd like to see is standalone `where` without needing to add `select` after it like in VB.net.
- int_19h 1y agoPattern matching shouldn't be hard to translate, really. It would not be a 1:1 mapping to the existing IEnumerable methods, but it's a straightforward translation to a single Select that returns a Nullable<ValueTuple> (to indicate match success/failure and pass the data in the former case) followed by a Where that would remove failures. Better yet, they could always add a new extension method to IEnumerable for this, and then translate to that. One feature I'd like to see is integration with foreach so that you don't have to repeat the variable and come up with a different name to work around shadowing rules. I.e. instead of: foreach (var x in from x0 ...) it would be nice to be able to write simply: foreach (from x in ...) and have it "just work", including more complicated cases with multiple nested from-clauses, let etc (effectively extending the scope of all of those into the body of foreach).
- deleted 1y ago[deleted]
- rafaelmn 1y agoLINQ methods are higher order functions ? LINQ syntax is just sugar and probably a design mistake (dead weight feature that I've only seen abused to implement monadic composition by insane people). And Ruby doesn't even enter this conversation if we're talking about these kinds of optimizations - it's an order of magnitude away from what you're aiming from if you're unrolling sequence operations in C#.
- alkonaut 1y ago> LINQ syntax is just sugar and probably a design mistake I find that the term "LINQ" these days tend to mean the extensions on IEnumerable/IQueryable, and not the special query syntax. Whatever the term meant when it was launched is now forgotten. Almost no one uses the special query syntax, but everyone uses the enumerable/queryable extension methods like Select() etc, and calls it "Linq".
- jermaustin1 1y ago> Almost no one uses the special query syntax Source? I'm in multiple current, active development projects with companies, they are all using the LINQ query syntax. Not to mention all of the legacy code out there that is under active maintenance. To say almost no one feels very much antithetical to my (albeit anecdotal) experience. I can't imagine, I'm the only c# consultant that has multiple clients that use LINQ queries extensively throughout their applications.
- alkonaut 1y agoTrying to crudely estimate the popularity i tried doing a regex search for C# statements ending with select ___; vs calls to Select(/Where(. It was (only) a factor 10x which was way less difference than I thought to be honest. I have seen and used one in the wild just a handful of times during 22 years of C#. But it might also vary with industry. It's likely a lot more common in fields where there are databases than where there are not. [1] https://github.com/search?q=%2F%28%3F-i%29%5Cs%2Bselect%5Cs%2B%5Cw%2B%3B%2F+language%3AC%23&type=code&ref=advsearch [2] https://github.com/search?q=%2F%28%3F-i%29%5Cs%2B%5C.%28Select%7CWhere%29%5C%28%2F+language%3AC%23&type=code&ref=advsearch
- tinco 1y agoLinq came out as part of a set of features that addressed the comforts of languages like Ruby. I don't know if they considered Ruby to be a threat at the time but they put a bunch of marketing power behind the release of linq. The way I understand it, as someone who jumped from C# to Ruby just around the time Linq came out is that it's a DSL for composing higher order functions as well as a library of higher order functions. I always liked how the C# team took inspiration from other language ecosystems. Usually they do it with a lot more taste than the C++ committee. The suppose the declarative linq syntax gives the compiler some freedom of optimization, but I feel Ruby's do syntax makes higher order functions shine in a way that's only surpassed by functional languages like Haskell or Lisp.
- whizzter 1y agoLike mentioned, groupby,etc all operate on functions, (map/reduce/filter/etc) are just named differently (select/aggregate/where/etc). What makes people love Linq is that it handles 2 different cases (identical syntax but different backing objects). 1: The in-memory variant does things lazily, select/aggregate/where produce enumeration objects so after the chain you add ToArray, ToList, ToDictionary,etc and the final object is built lazily with most of the chain executed on as few objects as possible (thus if you have an effective Where at the start, the rest of the pipeline will do very little work and very few allocations). 2: The compiler also helps the libraries by providing syntax-tree's, thus database Linq providers just translates the Linq to SQL and sends it off to the server, letting the server do the heavy lifting _with indexes_ so that we can query tables of arbitrary sizes with regular C# Linq syntax very quickly without most of it never going over the network.