Hacker Newsnew | past | comments | ask | show | jobs | submit | olmo's commentslogin

Glad to see someone pints this out. That’s the main reason I use React + Typescrip. JSX is an extension of javascript and can be fully checked while any template language is a custom invention that it’s hardly toolable.


If you're using a dynamic language, an ORM doesn't provide much. But in C# LINQ has the benefit of being strongly typed, this means your DB schema can be evolved. If you write raw SQL (or Python) and you rename a table/entity or column/property you gonna have a bad time. In C# you can just use a refactoring or, worst case, compile time errors.


Why LINQ is systematically ignored outside of Microsoftland? It's actually a type-safe expressive and secure AutomaticQueryGenerator


Like LINQ


Most enterprise web apps use bootstrap, that is quite Standart. But they do it on top of react/angular/grunt/we pack and a zillion npm packages to choose and keep updated. Nothing of this was necessary to make VB6 applications.


This is true, the monstrosity I inherited at work is built on bootstrap (2...and it was started after 3 came out..) but modern tooling has radically improved.

yarn/typescript and (though some days I hate it..it has gotten better) webpack largely make it feel sane(r).

That said getting to a point where I was comfortable with all three was insanely more complex and time consuming that picking up Delphi 6 was in the early 2000's.

Shrugs, the beast is what it is until someone does something better.


There is a solution for this problem: I use a monolith that make 100% of my sql queries using LINQ (including massive updates and so). Since Linq is strongly typed you can rename/remove/split tables and columns, fix compilation issues, create a migration and deploy the new monolith. We create an average of 5 migrations per day in a project with around 300 table for 2 years and no signs of an unmantainable mud so far.

Disclaimer: I'm the main developer behind Signum Framework


It's funny how async/await has influenced so many other languages but LINQ, that in my opinion is much more interesting (specially the DB stuff) for solving down to earth problems is sistematically ignored by other languages (Python, Java, JavaScript, etc...)


I guess you can argue that Haskell's do notation is exactly what LINQ (the grammar) is. F#'s computation expressions is a super-charged LINQ also.

I would like to see C#'s LINQ get an update. It seems to have been left to rot since Eric Meijer left the team. It doesn't even support the new values tuples where it's been fitted to every other part of the language:

    from (x,y) in Some((1,2))   // (x,y) will error
    select x + y;
The from x in y, let x = y, where x, select x, and, join x in y on a equals b, could and should be extended. Even better would be to allow custom operators like F#'s computation expressions.


To be fair, that feature is in the next version of C#; not release yet.


For me, LINQ is fundamentally list comprehensions on steroids. Way better than Pythons, about the same as using list functions in Haskell or F#, Java's finally caught up with its stream library.

The LINQ to SQL stuff annoys me, because while it works, it's a painful disaster to implement yourself against your own data stores. Believe me, I've tried.


In the case of Python and Java, I think it's because generator expressions and Streams, respectively, accomplish much the same thing.

Honestly, if you've seen what LINQ compiles to, it looks an awful lot like a Java 8 Stream.

Using Wikipedia's example of LINQ translation (https://en.wikipedia.org/wiki/Language_Integrated_Query#Lang...):

Written LINQ is:

    var results = from c in SomeCollection
                  where c.SomeProperty < 10
                  select new {c.SomeProperty, c.OtherProperty};
It compiles to:

    var results =
         SomeCollection
            .Where(c => c.SomeProperty < 10)
            .Select(c => new {c.SomeProperty, c.OtherProperty});
And in Java 8:

    Stream<> results = someCollection.stream()
                                     .filter(c -> c.getSomeProperty() < 10)
                                     .map(c -> new AbstractMap.SimpleEntry<>(c.getSomeProperty(), c.getOtherProperty()));
(of course, iterating over them is different; you just use a for loop in C#, but in Java you have to either use .forEach() or .collect() to a collection and then for over that)

I think Streams have more LINQ in them than most people think.

Disclaimer: it's been about a year since I've written Java 8, and this is off the top of my head (and the last time I used it, my employer's codebase had a class for pairs that was better than just SimpleEntry), so the code could be wrong.

Edit: and just for completeness... the same in Python generator expressions:

    results = ((c.some_property, c.other_property)
               for c in some_collection
               if c.some_property < 10)
Not very LINQ-like, but it serves the same purpose.


The thing you're missing is the way that LINQ creates an anonymous type, which is used to close over the values in the expression:

    var results = from a in x
                  from b in y
                  from c in z
                  select a * b * c;
Is very much more attractive than:

    var results = x.SelectMany(a => y.SelectMany(b => z.Select(c => a * b * c)));
If you use LINQ for more than just SQL queries (for monadic types like Option, Either, etc.) then these types of expression are commonplace. I'd certainly rather use C#'s LINQ grammar over its fluent API.


What you miss is that with LINQ you can extract the expression tree : https://msdn.microsoft.com/fr-fr/library/mt654263.aspx This is what is used to generate the SQL.


In the real world, MOST people are using the "it compiles to" version directly in the code. I certainly don't write the "from x in y select" version, except in the case of multiple hairy joins. Even those have become second nature at this point.

It's just more readable, and turns it into an object pipeline/functional programming style instead. The Java 8 streams were pretty much directly taken from LINQ and given their traditional functional names.


> The Java 8 streams were pretty much directly taken from LINQ and given their traditional functional names.

That was my point. I was disagreeing with olmo's suggestion that Java "systematically ignored" LINQ.


Ah okay, I misunderstood. Indeed.


> In the real world, MOST people are using the "it compiles to" version directly in the code

What's your source for this claim? Because anecdotally I don't see that at all.


Our codebase at work has hundreds if not thousands of LINQ queries, mostly using method syntax. I generally prefer it over query syntax except in a few cases, such when there's multiple joins or subqueries, or the when the statement is more than a few dozen lines. Occasionally a very complex LINQ statement requires using a `let` declaration which also is easier with query syntax. Luckily Resharper has an action to convert back and forth on the fly, so it's easy to use that to switch over when necessary.

I also don't use LINQ to SQL at all. It's all on in-memory stuff. I pretty much never write code like this:

    var result = new List<string>();
    foreach (var item in input) 
    {
        result.Add(item.Value);
    }
    return result; 
instead, using LINQ:

    return items.Select(x => x.Value);
The real power comes when you start mixing conditions:

    return items
        .Where(x => IsValidKey(x.Key))
        .Select(x => x.Value);
Or doing quick checks:

   if (items.Any(x => x == null || x.SomeValue == null)) 
       throw new InvalidArgumentException(nameof(items));


And now, with C#6 that last bit becomes:

if(items.Any(x => x?.SomeValue == null))


I think it depends on what the Linq to is. I find the sql like proper linq form only natural when databases are involved (and just barely).

Most uses of where/order/select in C# I'm pretty sure is linq to objects, not sql. I very rarely see the linq proper form in any C# code neither in OSS or in my dat job.


I never use the query syntax, or ever see it in any of the books or blogs I read, to the point that it threw me for a loop a little bit when I was studying for the C# certification exam, to see how emphasized it was. I learned that style long ago when I first started, but the fluent, extension method style is easier and less ugly, IMO, particularly when you start getting into more complex queries, or LINQ-to-SQL, where you end up wrapping your multi-line LINQ query in parentheses and materializing it by calling ToList() or ToDictionary() at the end.


https://blog.oz-code.com/analyzing-github-linq-usage-the-res...

Closest thing we have to real data, but it's been my experience in OSS and in professional life.


.net lambdas are in my opinion cleaner than linq syntax. java 8 implemented lambdas following .net success.


Linq is used pretty loosely to include also the equivalent form so

    dogs
       .Select(d => d.Id)
       .Where(d => d.Age > 3)
       .Skip(4)
       .Take(2)
would be considered just as much "linq" by most c# devs even though this isn't the query language integrated - simply because it's the same exact thing as the regular linq code.

I too find the "real" linq form mostly distracting.


The weird SQL-ish query syntax is an abomination. But using the LINQ extension methods, making use of lambdas as you say, is gold.

Most of it boils down to plain old functional map/fold/filter/zip constructs under different names.


Array.reduce(), Array.filter(), Array.map(), in JavaScript are pretty LINQ-ish if you ask me!


The thing with LINQ is that it can represent itself (reified or 'quoted code), so you can transform it into SQL, GPU instructions, whatever. This isn't a new idea, and F# had it before C# did (and LISP had it before, and others).

map/filter/reduce are just basic functional programming elements.


They are nothing even remotely likely linq. Those functions return the resulting arrays. Linq expressions are not executed until enumerated.

This allows you to compose linq expressions without computing intermediate results.


Sounds like Java 8 Streams, then.

Streams bear a pretty strong resemblance to translated LINQ.


It's true, but 95% of the cases you get much better results by using the right data structures (dictionaries) instead of transforming queries to loops. Still is a very cool thing, hopefully is standardized into Roslyn


Using the best structure is a good idea but simple LINQ is very readable if performance isn't a big concern.

BTW I cover this in my recent book: https://www.packtpub.com/mapt/book/Application%20Development...

You could try code samples and benchmarks: https://github.com/PacktPublishing/ASP.NET-Core-1.0-High-Per...


How would the provided example be better realized as a dictionary?


All true, but the example is a demo that doesn't do anything useful, and not typical code.


ReactComponent are also very OO, just the render function is functional


Of course it is! to start with, it looks like SVG, but also you only have to provide the state that you want and React adds and removes what is necessary, while in D3 you need to use `enter` and `exit` imperatively.

I'm just concerned about speed. Diffing works ok for forms but charts with 1000s of elements... let's see.

As someone who has worked with D3 and React a lot, D4 makes a lot of sense.

And the name is great!


enter() and exit() are declarative. You're not causing anything at all to happen, but rather declaring what should happen, in the form of a function, when new data is found or data becomes stale.


Declaring 'what' structure should exist

- vs -

Declaring 'how' this structure is created


D3 is more declarative than jQuery, but not so much as React.

selection.enter().append("div").attr("class", "bar") .style("height", function(d){ return d + "px"; }) .style(“margin-top”, function(d){ return (100 — d) + "px"; });

enter is not imperative, but what you write just afterwards is.


It sounds like the difference is just syntactical. Is this true? I have no experience with react, so I wouldn't know.


The problem is that calling a function called "enter" does not feel like writing declarative code.

It's an active verb and seems to imply an imperative style. Except it's actually declarative. The problem with d3 is that it takes a declarative system and gives it an imperative-looking API.


I think you're reading it wrong. `enter` isn't imperative. You're asking for the `enter` selection, which is the list of entering nodes. Same thing with `exit`. Calling either of those methods doesn't actually alter any data


I know enter isn't actually imperative. That's the problem: it looks like it should be.

If I write "node.enter()" it definitely looks like I'm making the node is being made to enter if you aren't well-versed in d3.


And SQL `SELECT` statements looks like I'm actively selecting something, when in reality I'm declaring what bits of the table I want returned... All syntax looks opaque until you understand the underlying concepts.


Uh, a SQL SELECT statement is actively selecting something. You're selecting what you want to return. Terrible example.

The problem with "enter" is that nothing will happen if you simply use enter by itself. Yet it's an active verb which seems to imply that something will be made to enter.


SQL SELECT declares what will be selected when the query is run. The query engine does the selecting, including figuring out how best to do it.


Yes, SQL is declarative.

But you still "SELECT" something to look at. A SELECT statement is, by itself, sufficient to get something to happen (for results to be fetched).

On the other hand, a D3 enter() does absolutely nothing by itself. You must do further calls for it to have any impact.

This is very off topic and ridiculous.


OK, if a SELECT statement is sufficient by itself, surely you can tell me the results of this:

    SELECT * FROM stuff WHERE thing=2
Of course you can't. Because every declarative process has two main steps: declare and execute. SELECT and enter() both only declare; they must then be executed against data in an engine to produce a result.


What we mean when we say "SQL is declarative" is that it doesn't provide instructions on how to carry out a task, and instead only provides a description of the outcome of the task, once it's been carried out. SELECT is declarative because it doesn't tell the computer how to do a query. SELECT tells the interpreter what you want not how to get it.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: