Live data from Hacker News

LINQ and Learning to Be Declarative

nickstambaugh.dev

21–30 of 60 posts

Re: LINQ and Learning to Be Declarative

#21
The example with lambdas should be written on multiple lines, too. At the same time, you can leverage the => syntax to avoid braces and end up with five lines:

    List GetExclusiveProducts(List source)
      => source
        .Where(p => p.ProductTitle == "iPhone")
        .OrderBy(p => p.TypeOfPhone)
        .ToList();
(You could join the first two lines, but I think that’s ugly for multi-line expressions.)

Also, less lines is not a good argument for SQL-style syntax vs method-call syntax. The good argument is that the SQL-style syntax is limited to only a few basic operations, when there are many more useful methods available.

Another reason is that this does not compile:

    List GetExclusiveProducts(List source)
    {
      return from p in source
             where p.ProductTitle == "iPhone"
             orderby p.TypeOfPhone
             select p;
    }
This method returns IOrderedEnumerable, not a list. To fix it, you would need to either change the return type, or go outside of the SQL-style syntax and call the ToList method:

    return (from ... select p).ToList();

Re: LINQ and Learning to Be Declarative

#22
post #14
post #2

> Functional programming isn’t an afterthought in C#, it’s effective and you should learn it if you haven’t already. I think C# is the best functional programming language because you always have access to a procedural code safety valve if the situation calls for it. 100% purity down the entire vertical is a very strong anti-pattern. You want to focus on putting the functional code where it is most likely to be wrong…

> 100% purity down the entire vertical is a very strong anti-pattern. It really isn't. The benefit of pure all the way down is that later you can replace bits with something more performant if necessary. But starting out with the idea that some bits should never be pure just means none of it is. The beauty of pure functional programming is that its very compositional nature means that you can replace a component with…

All of this!

"Pure functional" isn't a style choice. The judges won't hold up big placards with 10 on them because you executed your business logic in style.

It's a contract that your code will give the same output given the same input. The contract goes both ways: your ability to supply a caller with functional code is made easier by your callees supplying you with functional code.

Someone decides that that's draconian and says "what's the worse that can happen?" and starts mutating in a library dependency. Well now your backtracking parser may or may not be able to backtrack. Your transactional code may or may not be able to be rolled back. Your multi-threaded code may or may not be free of races. `true || f()` no longer means the same thing as `true`. You might need to start scaffolding all your unit tests with @Before and @After to setup and teardown state, and give up running them in parallel.

Maybe you really, really, really need to fire the missiles at the bottom of the call chain. Fine, just mark that method as 'red' so I get a compiler error when I try to serve up 'blue' code to my callers.

As long as you're showing off the syntax (matter of taste) on blog posts you might as well get some mileage out of the semantics (guarantees).

Re: LINQ and Learning to Be Declarative

#23

I like to return IEnumerable instead of List : IEnumerable GetExclusiveProducts(List source) => source .Where(p => p.ProductTitle == "iPhone") .OrderBy(p => p.TypeOfPhone); That way the user can decide if they want a List or Array or Set or whatever, and you can also add additional queries to this Also better to pass IEnumerable to the function instead of List, for the same reasons Also I forget the syntax but you ca…

Given the use case I’d consider IGrouping. My point being LINQ is a wide subject and most code I see barely touches the surface.

Re: LINQ and Learning to Be Declarative

#24
> Your coworkers and QA will thank you for learning LINQ and ditching the imperative methods that plague your Python brain.

This is a very unfortunate joke: Python has list (and generator) comprehension expression for a long time (2.3?) which are similar to LINQ. At some point in the history many languages stole useful expressions from other paradigms.

Let’s joke on BASIC, it always works.

Re: LINQ and Learning to Be Declarative

#25

I’m going to reserve a thread on this post for folks who want to share horror stories trying to implement their own LINQ providers.

Why?

Writing your own LINQ provider is a very niche activity done by people who want to translate or “transpile” C# expression trees into something else.

It is fundamentally a difficult endeavor because you’re trying to construct a mapping between two languages AND you’re trying to do it in a way that produces efficient target code/query AND you’re trying to do that in a way that has reasonable runtime efficiency.

Granted, on top of that, I’m sure LINQ provider SDKs probably add their own complexity, but this isn’t an activity that C# developers typically encourage.

Re: LINQ and Learning to Be Declarative

#26
post #14
post #2

> Functional programming isn’t an afterthought in C#, it’s effective and you should learn it if you haven’t already. I think C# is the best functional programming language because you always have access to a procedural code safety valve if the situation calls for it. 100% purity down the entire vertical is a very strong anti-pattern. You want to focus on putting the functional code where it is most likely to be wrong…

> 100% purity down the entire vertical is a very strong anti-pattern. It really isn't. The benefit of pure all the way down is that later you can replace bits with something more performant if necessary. But starting out with the idea that some bits should never be pure just means none of it is. The beauty of pure functional programming is that its very compositional nature means that you can replace a component with…

The problem is this tends to collide hard with things which are both stateful and mandatory ubiquitous, like logging.

"Functional core, imperative shell" is a great tradeoff position though.

>> Does F# care if a DLL it references was coded in a functional style

Deeper problem: it can't know. It can only assume. I'd have to check how the loader works but it may be the case that "first call to a function in an external DLL" is not stateless (and can error!) because it triggers the linker.

Re: LINQ and Learning to Be Declarative

#27
post #16
post #8

The second SQL-like version is far more readable. There is just less "syntax noise" and it's far more "declarative" by definition. The author stating that the lambda is "better" because it's less lines is also silly. It's been a while since I've written C#, but pretty sure the SQL-like version can be formatted to a single line as well: List GetExclusiveProducts(List source) => (from p in source where p.ProductTitle =…

You can format it on one line if you want. Please don't do that, though. Personally I prefer the method syntax with one method per line, it reads more linear than the query syntax.

Agree and disagree. I prefer the second approach, but I wouldn't format either as a single line.

Re: LINQ and Learning to Be Declarative

#28
post #8

The second SQL-like version is far more readable. There is just less "syntax noise" and it's far more "declarative" by definition. The author stating that the lambda is "better" because it's less lines is also silly. It's been a while since I've written C#, but pretty sure the SQL-like version can be formatted to a single line as well: List GetExclusiveProducts(List source) => (from p in source where p.ProductTitle =…

Never understood why a lot of programmers are so obsessed with reducing lines of code at the expense of all else. What's important to me is that I can understand the intent of the code, that I can reason about how that code will be executed at runtime, and that I can easily debug the code if needed. Of course, there's no need to go full enterprise Java. Never go full enterprise Java. But having ten lines of clear cod…

Not to mention it's much easier to put a breakpoint on one of those specific lines

Re: LINQ and Learning to Be Declarative

#29

The example with lambdas should be written on multiple lines, too. At the same time, you can leverage the => syntax to avoid braces and end up with five lines: List GetExclusiveProducts(List source) => source .Where(p => p.ProductTitle == "iPhone") .OrderBy(p => p.TypeOfPhone) .ToList(); (You could join the first two lines, but I think that’s ugly for multi-line expressions.) Also, less lines is not a good argument f…

There are some things that are harder to write in extension methods too. Such as `let` declarations. Or multiple from clauses referencing iterating variables from multiple levels. I use both.

Re: LINQ and Learning to Be Declarative

#30
post #24

> Your coworkers and QA will thank you for learning LINQ and ditching the imperative methods that plague your Python brain. This is a very unfortunate joke: Python has list (and generator) comprehension expression for a long time (2.3?) which are similar to LINQ. At some point in the history many languages stole useful expressions from other paradigms. Let’s joke on BASIC, it always works.

List comprehension is pretty good, but I prefer LINQ method-style because it's executed left-to-right, whereas I keep having to look up the order of Python.
Post reply on HN