Any tips? What kind of workflows might benefit the most if I were to incorporate it (to learn..)?
Any tips? What kind of workflows might benefit the most if I were to incorporate it (to learn..)?
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.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.
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.)
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#"));
<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.
%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.
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.
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-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/18a527bcc1f0bdaf54...
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.
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
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).
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.
names.ForEach(name=>Console.WriteLine($"Hello, {name}! Enjoy your C#"));
%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.
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#"))
To jump in a REPL (or any debug breakpoint observation facility), having optional type inference is a great plus to my mind.
Note that Crystal does allow to make type explicit, and keep the fluent interface on track doing so:
Array(String).new.push("Peter", "Julia", "Xi").map{|name| "Hello, #{name}"}.each{|greeting| puts "#{greeting}! Enjoy your Crystal"}
Let’s remark by the way that, like with C# lambda parameters, block parameters are not explicitly typed in that case.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?
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.
Just an FYI, discriminated unions are not product types, they are sum types. It's named so because the total number of possibilities is the sum of the number of possibilities for each variant.
Ex. A sum type Color is a PrimaryColor (Red, Blue, Yellow) OR a SecondaryColor (Purple, Green, Orange), the total number of possibilities is 3 + 3 = 6.
For a product type, if a ColorPair is a PrimaryColor AND a SecondaryColor, the total number of possibilities is 3 * 3 = 9
Both sum types and product types are algebraic types, in the same way that algebra includes both sums and products.
For the standard library, I'm curious for the family of TryParse kind of functions, since those are well modeled by a sum type. Maybe adding an overload without an `out` argument would give you back a DU to `switch` on