5 ms·
The funny thing is that you can write very similar code in C#, so maybe you don't need to switch which language you're using as a CLR frontend. using Syste
by pjc50 2y ago
The funny thing is that you can write very similar code in C#, so maybe you don't need to switch which language you're using as a CLR frontend.
using System.Linq;
using System;
var names = new string[] {"Peter", "Julia", "Xi" };
names.Select(name => $"Hello, {name}").ToList().ForEach(greeting => Console.WriteLine($"{greeting}! Enjoy your C#"));
LINQ is such a good library that I miss it in other languages. The Java stream equivalent just doesn't feel as fluent.
- bob1029 2y agoYou can write a vast majority of your C# codebase in a functional style if you prefer to. All the good stuff has been pirated from F# land by now: First-class functions, pattern matching, expression-bodied members, async functional composition, records, immutable collections, optional types, etc.
- guhidalg 2y agoI don't know if there's a name for it but essentially F# is where the language designers can push the boundaries and try extremely new things that 99% of users will not want or need, but eventually some of them are such good ideas that they feed back into C#. Maybe that's just research, and I'm glad that Microsoft hasn't killed F# (I do work there, but I don't write F# at work.)
- debugnik 2y ago> F# is where the language designers can push the boundaries It really isn't, not anymore. F# now evolves conservatively, just trying to remove warts and keep up with C# interop. And even then some C# features were considered too complex/powerful to implement (e.g. variance, scoped refs) or implemented in weaker, incompatible ways when C#'s design is considered messy (e.g. F#'s non-nullable constraints disallow value-types, which breaks for some generic methods written in C#, sadly even part of the System libs).
- UK-Al05 2y agoA language is just as much about what it can't do, then what it can do.
- bob1029 2y agoCan you elaborate on what you mean by this? I assume you are implying that too many choices could confuse a junior developer, which I agree with. However, I don't think this is a concern in the bigger picture when talking about the space of all languages.
- gonesurfing 2y agoMy 2p's worth is that the whole of F# is more than the some of its parts. When you say in your previous comment "All the good stuff has been pirated from F#" it misses the point of what it's actually like to use F#. The problem is, it's almost impossible to communicate what it's like. You have to try it and you have to keep going until you get over the initial "WTF!?" hump. There will be a WTF hump. For example, C# may have cribbed the language features, but F# is expression based and immutable by default. Try using the same features in this context and the whole game changes.
- UK-Al05 2y agoA language by making certain things harder makes the resulting code be built in a certain way. F# makes mutable code harder to do, so you tend to write immutable code by default.
- int_19h 2y agoI wouldn't say "all" - C# doesn't have discriminated unions yet, which is kind of a big one, especially when you're also looking at pattern matching. A
- caspper69 2y agoIt has been in discussion for quite some time. I believe they'll get there soon: (example) https://dev.to/canro91/it-seems-the-c-team-is-finally-considering-supporting-discriminated-unions-59k3 https://dev.to/canro91/it-seems-the-c-team-is-finally-consid... In the interim, MS demonstrates how C# 8.0+ can fake it pretty well with recursive pattern matching: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/patterns https://learn.microsoft.com/en-us/dotnet/csharp/language-ref... Not the same I know, and I would love me a true ADT in C#. Edit (a formal proposal): https://github.com/dotnet/csharplang/blob/18a527bcc1f0bdaf542d8b9a189c50068615b439/proposals/TypeUnions.md https://github.com/dotnet/csharplang/blob/18a527bcc1f0bdaf54...
- tubthumper8 2y agoThere's also going to be quite a big ecosystem / standard library difference between languages that had fundamental type system features since the beginning vs. languages that added fundamental features 23 years later. Imagine all the functions that might return one thing or another, which was inexpressible in C# (until this proposal is shipped), will all these functions release new versions to express what they couldn't express before? Will there be an ecosystem split between static typing and dynamic typing?
- caspper69 2y agoHaving reviewed the proposal (of course no guarantee that's what discriminated unions (aka product types aka algebraic data types) will look like), and it appears that it very much integrates nicely with the language. I don't suspect they'll make too many changes (if any) to the existing standard library itself, but rather will put functions into their own sub-namespace moving forward like they did with concurrent containers and the like. Given their penchant for backwards compatibility, I think old code is safe. Will it create a schism? In some codebases, sure. Folks always want to eat the freshest meat. But if they do it in a non-obtrusive way, it could integrate nicely. It reminds me of tuples, which had a similar expansion of capabilities, but the integration went pretty well.
- klysm 2y agoThis isn’t a great example of what linq is good at. There’s no reason to do ToList there, and the ForEach isn’t particularly idiomatic
- pjc50 2y agoYeah, I hit the problem that there isn't a null-type equivalent of Select() for Action<T>, nor is there a IEnumerable.ForEach (controversial), so that's a bit of a hack. But I wanted to make it as close to the original example as possible.
- bob1029 2y ago> There’s no reason to do ToList there In this case, I would move it to the very end if we are concerned about the underlying data shifting when the collection is actually enumerated. Forgetting to materialize LINQ results can cause a lot of trouble, oftentimes in ways that happily evade detection while a debugger is attached.
- klysm 2y ago> if we are concerned about the underlying data shifting when the collection is actually enumerated I’m not sure what you mean by this. You can fulfill the IEnumerable contract without allowing multiple enumerations, but that doesn’t really have to do with the data shifting around. Doing ToList can be an expensive and unnecessary allocation
- DeathArrow 2y ago
- voidUpdate 2y agoI love LINQ, maybe a little too much. I can end up writing monster oneliners to manipulate data in just the right way. I love list comprehensions in python too, since they can work in similar ways
- kkukshtel 2y agoModern C# collection expressions make the definition of names closer to F#: string[] names = ["Peter", "Julia", "Xi"]; I know working on "natural type" of collections is something the C# team is working on, so it feels possible in the future that you'll be able to do this: var names = ["Peter", "Julia", "Xi"]; Which I think would then allow: ["Peter", "Julia", "Xi"].Select(name => $"Hello, {name}").ToList().ForEach(greeting => Console.WriteLine($"{greeting}! Enjoy your C#"));
- pjc50 2y agoI did try that initially and got <source>(5,1): error CS9176: There is no target type for the collection expression. .. which I took to mean that, because .Select is an extension method on IEnumerable, the engine was unable to infer whether the collection should be a list, array, or some other type of collection. It seems reasonable to have it default to Array if it's ambiguous, maybe there's a downside I'm not aware of.
- DeathArrow 2y agoMaybe you can submit a proposal/issue to the C# language team? I'd vote for it!
- gibibit 2y agoFor reference, Rust provides a similar experience let names = ["Peter", "Julia", "Xi"]; names .map(|name| format!("Hello, {name}")) .iter() .for_each(|greeting| println!("{greeting}! Enjoy your Rust"));
- psychoslave 2y agoAs far as fluency goes, that’s not very impressive. %w{Peter Julia Xi}.map{"Hello, #{it}"}.each{puts "#{it}! Enjoy your Ruby"} That’s of course trivial examples. And while Ruby now have RBS and Sorbet, it’s yet another tradeoff compared to a syntax that has upfront static analysis as first class citizen in mind. That is, each language will have its strong and weak points, but so far on "fluency" I’m not aware of anything that really beat Ruby far beyond as Ruby does compared to other mainstream programming languages.
- int_19h 2y agoRuby is dynamically typed, which makes "fluent" API design that much easier at the cost of maintainability elsewhere. If you want to compare apples to apples, you need to compare F# to other statically typed languages.
- psychoslave 2y agoThat's exactly what I meant with the two last paragraphs.
- psychoslave 2y agoAlso note that the following is a valid Crystal-lang code: %w[Peter Julia Xi].map { |name| "Hello, #{name}" }.each { |greeting| puts "#{greeting}! Enjoy your Crystal" } As they put it: >Crystal is a general-purpose, object-oriented programming language. With syntax inspired by Ruby, it's a compiled language with static type-checking. But this time, one can probably say that Crystal will lake the benefits of ecosystem that only a large popular language enjoy. I guess on that side F#, relying on .Net, is closer to Kotlin with Java ecosystem.
- paddim8 2y agoThe only difference is that you have to specify the type of the list when you declare it though... That's not really a big deal. List<string> names = ["Peter", "Julia", "Xi"]; names.Select(name => $"Hello, {name}").ForEach(greeting => Console.WriteLine($"{greeting}! Enjoy your C#")) or new List<string> { "Peter", "Julia", "Xi" }.Select(name => $"Hello, {name}").ForEach(greeting => Console.WriteLine($"{greeting}! Enjoy your C#"))
- EVa5I7bHFq9mnYK 2y agoThat could be shortened to names.ForEach(name=>Console.WriteLine($"Hello, {name}! Enjoy your C#"));
- issafram 2y agoYou're being way too nice. Java stream is nowhere near as easy to use as LINQ. I'd say that LINQ is easily one of the top 10 coding features that Microsoft has ever created.
- DeathArrow 2y agoI think LINQ is inspired by SQL. You can do whatever you can with SQL, it's just that the data source might differ IEnumerable with some in memory data, IQueryable with some DB. Or you can use async enumerable and your data source can be whatever web API or protocol.