14 ms·
Every time the question of preferred programming languages comes up, I'm usually in the extreme minority with my preferences being Rust (for small/fast) and C#
by ComputerGuru 2y ago
Every time the question of preferred programming languages comes up, I'm usually in the extreme minority with my preferences being Rust (for small/fast) and C# (for productive and easy, where GC is acceptable), a combination that doesn't seem to appeal to too many people.
But for the projects that fall right about in the middle where it could go either way and I could see either language working, I almost always pick rust with discriminated unions being the biggest reason. It's incredibly hard to go back to a language without even basic ADTs after seeing the light.
- wk_end 2y agoInstead of C#, why not F#? You get proper ADTs among many other great features, but you still get all the utility of the .NET ecosystem.
- fluoridation 2y agoI get the feeling F# is a second-class citizen in the ecosystem. How likely is it (or is it at all possible) that I'm going to run into some library that doesn't work with F#?
- nightski 2y agoNone, it's a CLR after all. That said many libraries may not utilize the best features F# has to offer.
- antonyt 2y agoIt's impossible for a .NET library to not work with F#. It's very possible (and even likely) for a .NET library to prevent you from writing idiomatic F#. You're right that it's a second-class citizen.
- debugnik 2y ago> It's impossible for a .NET library to not work with F#. This isn't true, C# has been adding new ABI features that didn't interact correctly with F# until the compiler and tooling catched up. For example, the spanification of C# was a huge a pain point and it still is when it comes to tooling.
- antonyt 2y agoTIL. Have links to any details about this? I'm very curious!
- pjmlp 2y agoStuff like Roslyn analysers, code generators and interceptors, only take C# semantics into account, the first one also works with VB.NET. Since its introduction that CLR has the notion of CLS, the Common Language Subset, that any language targeting the CLR should be able to understand. Anything in the MSIL or metadata, that isn't part of that, requires additional effort from the respective language to be able to expose those features, and many of the more recent improvements, are more in the sense of CLR meaning C# Language Runtime, than Common Language Runtime.
- debugnik 2y agoYou mostly have to look at the time frames between C# adding features with new ABIs and the time it takes for F# to announce they can actually consume them. For example, F# used to crash the CLR with InvalidProgramException when setting C# `init` properties. [1] It took almost three years, I think, to release the fix. [1]: https://github.com/fsharp/fslang-suggestions/issues/904 https://github.com/fsharp/fslang-suggestions/issues/904 Another rough example would be spans, and their more general feature, byref-like types (ref struct). These required plenty of compiler support, as they've got special lifetime rules (and more pending to implement `scoped`), they are banned as generic type arguments, and they require ignoring a special Obsolete attribute. While these were added to F# timely, many language features still break when they interact with them: local functions, computation expressions (even the built-in ones), recursive type inference, and generic intrinsic methods such as `raise`, `defaultof` or `typeof`. This wouldn't be so bad if C# hadn't "spanified" the shared framework and the entire ecosystem without CLS alternatives for many APIs. So, these natural F# snippets don't compile: let numbers = [| for span in text.EnumerateLines() -> Int32.Parse span |] let checkNonEmpty (span: ReadOnlySpan<'T>) = if span.Length > 0 then span else failwith "Expected non-empty span." Edit: And I haven't even gotten into the libraries that use reflection expecting you to declare types in ways F# doesn't support.
- Eji1700 2y agoJust to add to the other comments, in my experience a large majority of libraries work fine. Maybe a little tweak here or there, or maybe you need to use some C# esq syntax (which is harder in my case because I so rarely do now). Generally though, it's pretty easy. Sometimes you'll want to make bindings around various things (not that you need to, but it'll make things smoother). It's not actually awful, it's just that there's no real documentation of "hey today we're going to take Serilog/whatever and show you how to configure it in F#" style videos, so depending on where your weaknesses lie it can feel frustrating.
- gopherchucks 2y agoMy experience mirror yours. I really lean into the functional core, imperative shell because of this. Im mostly interacting with C# flavored libraries at the edges and I don’t try to force F# paradigms there, I just roll with the punches.
- DaiPlusPlus 2y agoThe benefits of F# only really apply when using a 100% F# codebase. Try doing WinForms in F#...
- Eji1700 2y agoI mean that's mostly pretty easy bindings, but yeah it's annoying that you have to do them and feels like you're losing out on the whole damn point of using F#
- Archelaos 2y agoThat F# has no native GUI framework is the reason why I stick with C#. When coding something with a GUI, the majority of my development time is typically spent in the GUI layer. The rest is some more or less straightforward object relational mapping with some validation an calculations in a business layer where I use Linq to emulate functional programming in C#. Adding F# to the game would only complicate the scenario, because I would need to connect the F# interfaces somewhere to C# anyway, requiring an additional layer of mappings in many cases.
- neonsunset 2y agoThere is! https://funcui.avaloniaui.net/ https://funcui.avaloniaui.net/
- Archelaos 2y agoIt is just a wrapper around Avalonia, which is written in C#.
- neonsunset 2y agoIt is (together with FuncUI Elmish) an extension for Avalonia to write GUI applications in F#. What difference does it make if Avalonia itself is written in C#?
- lp0_on_fire 2y agoNothing against F# but the developer ecosystem around C# is just plain better, especially if you're already a dotnet shop. Documentation, code examples, tooling, developers who already know the language, etc. F# doesn't really buy you anything if you're already invested in C# (or even VB.net for those poor souls) unless you have a very specific use-case for it, IMO.
- rafaelmn 2y agoF# has it's own warts, tooling isn't as polished, stuff like type providers sound really cool but suck in practice IMO, file ordering being relevant for compilation is bleh... Every time I try to use it I'm left with a feeling it's not worth the hassle over C#. C# has been quite nice for 10 years and they keep improving consistently with every version.
- hnthrow289570 2y agoThe language itself is nice, the code bases that companies produce with it is not, and sadly that reputation plays into your decision to choose a career stack. You're going to have patterns from the .NET Framework era being ported to .NET Core projects. It works, but you'll have two paradigms of doing things mixed into your project. I envy people who only do hobbyist C# so get to work on code bases that have all the newest language feature usage.
- rafaelmn 2y agoI definitely dislike most C#/.NET developers/community (every time mediator is mentioned I want to stab myself) and would rather work with people in F#/FP. But when you have to work on "diverse" development teams having some sort of patterns established (flawed as they are) brings some order to the insanity.
- xeromal 2y agoMy brain really likes how organizes C# libs tend to be compared to the 50 different organization schemes I deal with in node and python
- bbkane 2y agoDoes C# impose a lot of organization? I've only worked in one C# codebase but it has partial classes everywhere and TONs of abstraction bloat. I found it difficult to reason about the organization.
- GiorgioG 2y agoBecause nobody uses it, Microsoft doesn’t invest or promote F# heavily. I’m pissed about all of this, but I accept that eventually C# will get much of F#’s goodness.
- Akronymus 2y agoI don't think that c# will ever get immutability by default though.
- throw868788 2y agoIndeed. The company I work for uses F# for large revenue workloads across many services; mostly coming from non .NET dev's. It handles large scale customer traffic quite well without a hiccup and with the C# interop we never find we are blocked (e.g enterprise/vendor libs). They found it easier to learn F# than C# - it has a lot more in common with JS/Go/etc in how code is structured and maintained from their POV. Good mentorship is critical for learning and deriving extra value from it especially if coming from old C#/Java/etc. The push for C# to minimal APIs, less classes, etc from our experience has slowly made it less necessary to have F# wrappers as well - the interop ugliness usually only resides in one file (e.g. ASP.NET Startup.fs or equilvalent in given C# framework). Given our proprietary nature however we don't broadcast a lot of our dev effort/development online - I assume many F# shops are/were similar. We've created very large scale applications in it requiring significant throughput. One of its benefits is also its disadvantages - we typically are quite productive in it and so don't feel the need to hire as many people in the team. Before LLM's were a thing we found we were wasting less time with boilerplate in general than our C# code for example. YMMV.
- deleted 2y ago[deleted]
- mlinhares 2y agoC# is great, likely the best mainstream programming language nowadays, but its in the hands of microsoft and microsoft didn't really care much about building a community or getting it to work natively in other OSes/toolchains. Its a shame, they even had a second change when Oracle bought sun and no one knew what was going to happen with Java, but fumbled that as well.
- hnrodey 2y agoCome again?
- msk-lywenn 2y agoThis comment feels like it's been written 20 years ago. C# runs natively anywhere and this has been true for at least a decade.
- nullindividual 2y agoI'd like a supported port of .NET to the BSDs.
- neonsunset 2y agoThere is one: https://www.freshports.org/lang/dotnet https://www.freshports.org/lang/dotnet pkg install lang/dotnet Note that not everything will work, and it is community-supported. But the effort is there, and there are contributions to dotnet/runtime from time to time to further improve or fix it. It's in a better state than it was 2 years ago.
- DaiPlusPlus 2y ago> but its in the hands of microsoft and microsoft didn't really care much about building a community or getting it to work natively in other OSes/toolchains. That statement was true - until 2016. Times change, Microsoft changed.
- pathartl 2y ago
- giancarlostoro 2y agoFor me its C# and Python, though I like Rust, D and lately been getting into Nim. I want to like Lisp, but its just not something I see someone paying me to work in.
- radicalbyte 2y agoC# for real work, Python for scripting or specific use-cases where it has excellent library support & Golang if I need something closer to C or very lightweight or easy for people to understand. Rust is interesting but the compile times aren't great.
- giancarlostoro 2y agoI use Python for real work too, but my current employer does not use it as much.
- radicalbyte 2y agoIt's too dynamic/slow for me and the dependency system is a mess to the point where the entire Javascript world is better. Actually I forgot TypeScript, been using that for more than a decade now. So much better than the dark old days of JavaScript :)
- paulddraper 2y ago> It's incredibly hard to go back to a language without even basic ADTs after seeing the light. How did we ever prioritize implementation inheritance over ADTs? I don't know, but it was a mistake.
- JoshTriplett 2y agoHow widely understood and appreciated were algebraic data types at the time Cfront was first floated as the precursor to C++? To what degree had they shown up in mainstream languages?
- tialaramex 2y agoWell if you want to compare to why C++ has multiple inheritance, you need to first explain which mainstream languages in the mid-1980s had multiple inheritance so we can contrast. Like algebraic data types, multiple inheritance wasn't novel, but what were the big famous languages from that time which showed this was a must have for Bjarne's language?
- JoshTriplett 2y agoThat's not the comparison I'm making. It's possible for a proposed language to add something despite not being popular at the time, but that's not the default. I'm suggesting that if ADTs were not already popular at the time, it would be the unsurprising default for them to not be in a new language. In today's language landscape, by contrast, it would be surprising and disappointing for a new language to not have either ADTs or a specific alternative they propose for solving the same problem.
- tialaramex 2y agoBut the actual answer is revealing. Bjarne implemented multiple inheritance in C++ because it was easy. It's a New Jersey language. The priority is simplicity of implementation. It's not about what was popular, or that Stroustrup was at Cambridge not Edinburgh (all the exciting Programming Language theory stuff in that era like ML was from Edinburgh as you perhaps know). If ADTs were easy, C++ would have ADTs.
- CharlieDigital 2y agoIt's possible to add DUs in C# today with some third party packages. - https://github.com/domn1995/dunet https://github.com/domn1995/dunet - https://github.com/mcintyre321/OneOf https://github.com/mcintyre321/OneOf Quite good and ergonomic with the source generators removing a lot of the boilerplate. I have a practical example here using OneOf with .NET Channels: https://chrlschn.dev/blog/2024/07/csharp-discriminated-unions-and-dotnet-channels/ https://chrlschn.dev/blog/2024/07/csharp-discriminated-union...
- jeremycarter 2y agoActually not a bad solution. Thanks for sharing
- pseudopersonal 2y agoYou must really hate REPLs. You cling to your ADTs, I cling to my REPLs.
- indrora 2y agoI can’t speak to Rust but there have been plenty of C# repls in the past. https://fuqua.io/CSharpRepl/ https://fuqua.io/CSharpRepl/ For one
- maxbond 2y agoI've seen comments like this a few times, and I think there's a misunderstanding at play. I think people who are used to using REPLs look at people who aren't and conclude that, since they don't have a REPL in their toolbox, they don't have a tool in there that does what a REPL does. But I think most of the time, they are accomplishing the same tasks with a different workflow. For instance, I use throwaway files instead of REPLs, even when I have access to one. I'm still running small and isolated experiments to build my understanding, but I get to use the editor I'm comfortable with and it's easy to copy the code into my project afterwards. The other thing I used to use REPLs for was introspection/looking up documentation, which my LSP handles nicely. You can think of the LSP as a sort of REPL integrated seamlessly into the editor; when I have a question, I'll query the LSP by writing a line of dummy code that causes the LSP to generate an annotation with the answer. So for instance if I want to know if `foo` implements a certain trait/interface, I can write a variable declaration like `let x: Box<dyn MyTrait> = Box::new(foo)` and see if my LSP annotated that as a type error. I can do this very quickly and without leaving my editor, so it helps me stay in the flow of things.
- CharlieDigital 2y agoThere's a really nice VS Code extension called Polyglot Notebooks that's great for running small C# "scripts"
- drdaeman 2y agoIs there a contradiction? I'm not aware about Rust or C# REPLs (a lot of results comes up, but no clue how serious are those), but GHCi surely proves that you can have both.
- tester756 2y agoI've been writing C, C++, C# and some js/sql/ts/python for money. Lua for lulz. And *nothing* gets even fucking close in terms of productivity to C#. Great language, mature and robust ecosystem with sane compilation times and great tooling: package manager, test runner, strong debugger, one CLI with almost all tools needed. I wish C++ was half as enjoyable as C# is.
- TillE 2y agoI'm a big fan of C#, but to be fair nothing else you've named is really aiming for the same niche. The better comparison would be Swift, Go, Java/Kotlin, stuff like that. But yeah I think C# is often unfairly viewed as a boring enterprise-y language when it's actually become a very comfy swiss army knife.
- LtWorf 2y agoIf it wasn't so linux distribution unfriendly…
- nickcox 2y agoIn what ways?
- LtWorf 2y agoBasically it's not included in any distribution. Mostly for license problems. Which means anything you write with it can't be included in any distribution. It's quite limiting. Basically it's only useful for proprietary software shipped by 3rd party.
- neonsunset 2y agoThe entirety of https://github.com/dotnet/dotnet https://github.com/dotnet/dotnet (which is a VMR for full-source build of Roslyn, runtime and everything else that goes into runtime-only and SDK packages) is MIT, which is as permissive as it gets, save for CC0 or Unlicense. Quick search shows that SDK and runtime packages are available in the official feeds for Archlinux: https://archlinux.org/packages/?sort=&q=dotnet https://archlinux.org/packages/?sort=&q=dotnet Fedora: https://packages.fedoraproject.org/pkgs/dotnet8.0/ https://packages.fedoraproject.org/pkgs/dotnet8.0/ Ubuntu: https://pkgs.org/search/?q=dotnet https://pkgs.org/search/?q=dotnet I always wondered what is the motivation behind the negative comments like these on .NET submissions. Is this because .NET is mostly made by MS employees instead of Google (which is an AdTech company) or Oracle (which has a license trap JDK distribution)?
- foota 2y agoI also really like rust's support for deriving traits. Being able to generate hashes, equality, debug strings, etc., is really convenient for hacking around.
- jiggawatts 2y agoI’m in the same boat, and while I love the concepts behind Rust I’m not a fan of the syntax. What I’d love to see is a hybrid between C# and Rust that has the capabilities of both languages in “layers”. So business logic would be written in a simple GC variant of the language that feels like C# but the underlying standard library and low-level packages could use Rust-like semantics. This is already the direction that C# is moving in: it’s getting more and more features related to “ref” and other low-level primitives. Sadly Rust and C# have fundamental incompatibilities such as different string encodings, so they can’t be directly merged.
- pdimitar 2y agoFor me it's Elixir / Golang and Rust. Between these 3 I can serve all needs.
- karmakaze 2y agoI was disappointed with Rust not being able to do ad-hoc unions, as well as the flippant you don't need that mentality of the community.
- deleted 2y ago[deleted]