[HN Gopher] Official proposal for Type Unions in C#
___________________________________________________________________
Official proposal for Type Unions in C#
Author : Fervicus
Score : 198 points
Date : 2024-08-07 17:02 UTC (5 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| zamalek wrote:
| > The interior layout of the union struct is chosen to allow for
| efficient storage of the data found within the different possible
| member types with tradeoffs between speed and size chosen by the
| compiler.
|
| Having _attempted_ (and being bitten by) far too much black magic
| with C# unions in the past (using FieldOffset), there is an
| unfortunate situation here: aliasing a pointer/ref value and
| value is UB. This means that a struct union of a u64 and an
| object would need separate fields for each, wasting 8 bytes. That
| is, unless the ryujit/gc is updated with knowledge about this.
| tombert wrote:
| Huh, I did F# for years with discriminated unions, and I guess I
| just assumed C# would have had them by now.
|
| I know not everyone likes them, but for typed languages I find it
| extremely hard to go back to languages without ADTs of some kind.
| I do Java for my current job, and Java is generally fine enough,
| but it's a little annoying when I have to do whacky workarounds
| with wrapper classes to get something that would be done in three
| lines of F#.
| Eji1700 wrote:
| F# is so hard to walk back from. I wish Microsoft would support
| it better and actually push it, because it's such a perfect
| sweet spot. Most of the functional advantages without being
| shackled to pure functions and the like is so easy to develop
| in.
|
| Instead they've been, very slowly, turning C# into F#, which is
| even weirder to watch.
| ctenb wrote:
| It makes sense from a language adoption standpoint,
| especially if you look at typescript for example, which is
| also by Microsoft. Though I agree with you personally
| tombert wrote:
| I agree; F# is probably my favorite of the "compromise"
| functional languages [1], where you can drop into the "wrong"
| way when necessary. F# pushes a more or less pure approach,
| but in some cases, like when mutation will be a bit easier
| and/or faster, it's easy to do that as well. I also think
| that even F#'s OOP is actually really pleasant...If nothing
| else, it's a lot more terse than C#'s.
|
| I miss writing it; I haven't had a job using it in a few
| years but I really enjoyed writing code in it when I did.
| Most of my personal projects haven't really been able to use
| .NET for awhile, so I never seem to have an excuse to play
| with F# in my personal time.
|
| I never got into C#, so I can't say that I really feel the
| pain of the C# transition into F#.
|
| [1] At least in the typed world. I'm also really partial to
| Clojure.
| kriiuuu wrote:
| I feel the same about Scala. I use Scala3 daily and almost
| every other language is such a step back. I have looked at F#
| and it looks like one of the only other languages I would
| enjoy as much as Scala. Haskell is nice too, but the
| ecosystem is just not quite there. F# being able to tap into
| the rich C# ecosystem and Scala being able to tap into the
| Java ecosystem is such a win and makes them feel a lot less
| niche when you use them.
| tombert wrote:
| I do like Scala, and I haven't touched Scala3, but I've
| found it pretty unwieldy for actual use. It feels like I'm
| constantly fighting with the type system in a way that ends
| up being annoying an unpleasant.
|
| To be clear, it's not like I'm new to functional languages
| and their type systems, I've been doing Haskell for
| forever, and I did F# for a multiple years, but Scala has
| never really clicked for me.
|
| Personally, for doing JVM stuff, I'm a pretty die-hard
| Clojure advocate. I feel like it's easy for me to write
| Clojure in the way that I think, while still allowing me to
| mooch off the entire Java ecosystem, and if there are
| things that I don't like about the language it's really not
| _that_ hard to macro in a new feature (though obviously
| this should be used sparingly).
|
| I definitely recommend giving F# a try. I think it's an
| extremely underrated language.
| agent281 wrote:
| > I definitely recommend giving F# a try. I think it's an
| extremely underrated language.
|
| Do you have any recommendations for people who do not
| have C#/.NET experience who want to rip their toes in F#?
| The last time I tried the language I bumped my head on
| the .NET parts. :/
| tombert wrote:
| Out of curiosity, what confused you about the .NET stuff?
| I didn't have any .NET experience going into F# either
| [1] and I didn't find it too hard to pick up the .NET
| stuff.
|
| For the most part I didn't need most of the built in .NET
| libraries; the F# stuff was fine, but the ones I ended up
| using a lot were the threadsafe libraries for when I
| needed mutation across threads. ConcurrentDictionary was
| one I used an awful lot, ConcurrentBag occasionally,
| SemaphorSlim, and Interlocked Incrementors.
|
| The reason that the .NET compatibility was handy to me
| was because it made it easy to get third party libraries
| without much fuss, which was great because they were
| generally pretty well supported.
|
| The rule of thumb that I used was that F#, while it kind
| of looks like Haskell, is not Haskell, and specifically
| it's not lazy, and as such I always kind of pretended I
| was in the `do` block. Things execute top down, and you
| can mix in side effects wherever, so you kind of have to
| pretend everything is in an IO monad, or at least if you
| see anything that has a side effect in there.
|
| [1] I was hired at Jet.com specifically because I had
| Haskell and Erlang experience prior. I had never written
| any significant C# code before.
| agent281 wrote:
| I was working on a Linux laptop and the installation
| process wasn't immediately clear. Some of the frameworks
| I looked at didn't target the most recent .NET version so
| I had to install multiple versions. Once I had it
| installed, I had compilation failures with a project that
| was built on Windows. The team that ran it wasn't sure
| what was happening.
|
| Also, having the documentation split between the F# parts
| on one site and the .NET parts on another site was a bit
| of a pain.
|
| It might have gone better if I was starting with a book
| instead of picking docs off the web.
| tombert wrote:
| Ah, yeah, the non-windows stuff was pretty clunky for
| awhile, but I do feel like it's gotten a bit better at
| the command line support.
|
| FWIW I think it works fine with Nix, so if you're not
| opposed to using that package manager it should pretty
| trivial to get different versions working with a nix
| shell and/or flake.
| progmetaldev wrote:
| Hopefully this website can get you further with the
| installation. There will probably still be issues between
| Windows and Linux specific tutorials, depending on what
| you are trying to do.
|
| https://fsharp.org/use/linux/
| pjmlp wrote:
| It is a dream learning guest languages, while trying to
| avoid the platform, one really needs to understand UNIX,
| Web, .NET, Java, Erlang... for using whatever alternative
| leaky abstractions are provided on top of them.
|
| In F#'s case, there are plenty of good books, and then it
| is really needed to learn the platform.
|
| Some well known ones => Stylish F#, F# in Action, Domain
| Modeling Made Functional
| progmetaldev wrote:
| Thank you for the recommendations. I still find using a
| physical book easier to learn from, even if they do tend
| to be out of date faster than online resources. I feel as
| though F# doesn't move as fast as other parts of the .NET
| ecosystem, and in particular the Domain Modeling Made
| Functional seems like it will be relevant for years to
| come.
| progmetaldev wrote:
| While a bit dated, F# For Fun and Profit is a great
| learning resource:
|
| https://fsharpforfunandprofit.com/
| electroly wrote:
| I'm glad they're simply turning C# into F#. They're coming to
| us where we are, rather than forcing us to make a jump. I'm a
| relatively "blue collar" developer, I know a little about FP
| (not enough to be productive in F#) but I have tons of C#
| experience. I appreciate them taking the good stuff from F#
| and making it understandable to C# developers. It's been a
| delightful progression; no big jumps, no paradigm shifts,
| just the steady addition of useful new features that I can
| understand.
| Eji1700 wrote:
| So the issue for those of us in F# land, is that it's
| really not a big jump from C#. I've taught it (lightly) to
| at least one C# dev who basically picked it up in a
| weekend.
|
| Something that helps, a ton, is as you're transitioning,
| you can write code almost identically to how you did
| before. It doesn't force FP on you at all. It's less useful
| if you try to do that, because you're not taking advantage
| of the language, but it makes testing your beliefs on how
| things work SUPER easy because you can set it up in the OOP
| way, get the result you expect, then set up in what you
| think is the correct FP way, and see if it matches.
|
| The only issue is there's a severe lack of beginner
| friendly documentation (although it's leagues better than
| it used to be). I honestly think that if you're a C# dev,
| it's probably worth giving it a weekend or two to play
| with. ESPECIALLY if you like linq syntax.
| progmetaldev wrote:
| I agree with you, as far as adding new features to C# from
| F#. When I have the time to refactor larger codebases, I'm
| often finding new C# features/syntax makes the code easier
| to understand and reason about (often due to decreasing the
| number of lines needed to accomplish the same thing,
| without overcomplicating things). I do make sure that if
| I'm introducing new language features, that I'm refactoring
| related portions of code, so I'm not leaving behind the
| "old" way of doing things while also introducing the "new"
| way for the same functionality. I'm always thinking of the
| next developer with anger issues coming into the codebase
| after me.
| kriiuuu wrote:
| Good news is that you can achieve this with relatively little
| boilerplate in Java with sealed interfaces and records now.
| Relative to Java that is
| tombert wrote:
| Yeah, I know, and I have started using those, though that
| doesn't undo the last 15 years of Java code that I've written
| where that wasn't really an option.
|
| Still, good to see Java joining the 21st century at least.
| Arnavion wrote:
| As of 2020 (when I stopped using F# and .Net in general), the
| CLR only had inheritance and F#'s enums were actually
| implemented using inheritance. Eg Some and None were derived
| classes of Option class. You would see it if you inspected an
| F# assembly in a decompiler. I don't know if it's still the
| same today. This C# proposal has anonymous enums using `A or B`
| syntax which would be hard to make work as sugar over
| inheritance, so I guess the CLR would support enums first-class
| for this to work (if it doesn't already).
| arwhatever wrote:
| I've lost track of all of the red/blue/white/black pill color
| metaphors, but unions with exhaustive pattern matching is one of
| the toughest of all programming language features to live without
| once you become aware of it.
|
| I've never felt like I've fully understood the implications of
| the expression problem
| https://en.wikipedia.org/wiki/Expression_problem but my
| best/latest personal hypothesis is that providing extension
| points via conventional polymorphism might be best suited for
| unknown/future clients who might extend the code, but unions with
| exhaustive pattern matching seem better suited for code that I or
| my team owns. I don't typically want to extend that code. More
| often, I instead want to update my core data structures to
| reflect ongoing changes in my understanding of the business
| domain, more often than not using these Union-type relationships,
| and then lean on the compiler errors maximally to get feedback
| about where the rest of the imperative code now no longer matches
| the business domain data structures.
| peheje wrote:
| Maybe I'm off, but to me the gist of the expression problem can
| be explained by contrasting how code extensibility is achieved
| in OOP/FP.
|
| OOP Approach with interface/inheritance:
|
| Easy: Adding new types (variants) of a base class/interface.
| Hard: Adding new functionality to the base class/interface, as
| it requires implementing it in all existing types.
|
| FP Approach with Discriminated Unions:
|
| Easy: Adding new functions. Create a function and match on the
| DU; the compiler ensures all cases are handled. Hard: Adding
| new types to the DU, as it requires updating all existing
| exhaustive pattern matches throughout the codebase.
|
| Here's some Kotlin code. Kotlin is great because it can do both
| really well. // Object-Oriented Approach
| interface Shape { fun area(): Double fun
| perimeter(): Double } class Circle(val radius:
| Double) : Shape { override fun area() = Math.PI \*
| radius \* radius override fun perimeter() = 2 \*
| Math.PI \* radius } class Rectangle(val width:
| Double, val height: Double) : Shape { override fun
| area() = width \* height override fun perimeter() = 2
| \* (width + height) } // Easy to add new shape
| class Triangle(val a: Double, val b: Double, val c: Double) :
| Shape { override fun area(): Double {
| val s = (a + b + c) / 2 return Math.sqrt(s \* (s
| - a) \* (s - b) \* (s - c)) } override fun
| perimeter() = a + b + c } // Hard to add new
| function (need to modify all existing shapes) //
| interface Shape { // fun area(): Double //
| fun perimeter(): Double // fun draw(): String // New
| function // } // Functional Approach
| sealed class ShapeFP { data class CircleFP(val
| radius: Double) : ShapeFP() data class
| RectangleFP(val width: Double, val height: Double) : ShapeFP()
| } fun area(shape: ShapeFP): Double = when (shape) {
| is ShapeFP.CircleFP -> Math.PI \* shape.radius \* shape.radius
| is ShapeFP.RectangleFP -> shape.width \* shape.height }
| fun perimeter(shape: ShapeFP): Double = when (shape) {
| is ShapeFP.CircleFP -> 2 \* Math.PI \* shape.radius
| is ShapeFP.RectangleFP -> 2 \* (shape.width + shape.height)
| } // Easy to add new function fun draw(shape:
| ShapeFP): String = when (shape) { is ShapeFP.CircleFP
| -> "O" is ShapeFP.RectangleFP -> "[]" }
| // Hard to add new shape (need to update all existing
| functions) // sealed class ShapeFP { // data
| class CircleFP(val radius: Double) : ShapeFP() //
| data class RectangleFP(val width: Double, val height: Double) :
| ShapeFP() // data class TriangleFP(val a: Double, val
| b: Double, val c: Double) : ShapeFP() // }
| arwhatever wrote:
| I think you've nailed the definitions.
|
| However the definitions make the 2 choices (adding new types
| vs adding new functions/operations) sound like a toss-up.
|
| It is the fact that I tend to find the FP/DU approach so much
| more frequently useful for my/my team's own code that makes
| me wonder if I'm missing something.
|
| Perhaps the important distinction I've been missing is in
| Wikipedia's definition:
|
| "The goal is to define a data abstraction that is extensible
| both in its representations and its behaviors, where one can
| add new representations and new behaviors to the data
| abstraction, without recompiling existing code, and while
| retaining static type safety (e.g., no casts)."
|
| ... but when I'm working on my own/team's code, it is
| perfectly sensible to recompile the code constantly.
| jerf wrote:
| The reason why it matters less than people intuitively
| think is precisely that it matters a lot less when you're
| in full control of both the operations and the types
| anyhow, and that's actually the most common case. Generally
| you are "composing" in library code, that is, just _using_
| it, not extending the library itself.
|
| When you are extending, you actually want to choose the
| correct thing depending on what you need. Going the wrong
| direction is painful in both directions.
|
| Personally I think one of the reasons sum types are greeted
| with such "oh my gosh where have you been all my life"
| reactions is precisely that we had type extension as our
| only option for so long. If we had had only sum types, and
| type extension was given to us for the first time in
| obscure languages 20 years ago and they only really started
| getting popular in the last 5 or so, I think they'd be
| considered in much the same way. Just as in a world with
| only screwdrivers, the invention of the hammer would be
| hailed as a revolution... and in a world with only hammers,
| the invention of the screwdriver would be hailed as a
| revolution. But in both cases the real mystery is how the
| hypothetical world got that far in the first place.
|
| Not that they aren't useful; consider what it means that
| I'm analogizing them to something like a hammer and a
| screwdriver, not an oil filter remover or something. It is
| weird that we were missing one of them for as long as we
| were in the mainstream.
| arwhatever wrote:
| Sum types are not a new discovery for me, personally.
| ComputerGuru wrote:
| 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 wrote:
| Instead 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 wrote:
| I 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 wrote:
| None, it's a CLR after all. That said many libraries may
| not utilize the best features F# has to offer.
| antonyt wrote:
| It'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 wrote:
| > 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 wrote:
| TIL. Have links to any details about this? I'm very
| curious!
| pjmlp wrote:
| Stuff 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 wrote:
| You 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
|
| 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 wrote:
| Just 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 wrote:
| My 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 wrote:
| The benefits of F# only really apply when using a 100% F#
| codebase.
|
| Try doing WinForms in F#...
| Eji1700 wrote:
| I 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 wrote:
| That 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.
| lp0_on_fire wrote:
| Nothing 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 wrote:
| F# 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 wrote:
| The 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 wrote:
| I 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 wrote:
| My 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 wrote:
| Does 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.
| xeromal wrote:
| I don't think I've really seen a partial class since the
| webforms/winforms days about 15 years ago. Maybe XAML too
| but I haven't used XAML in so long.
|
| I think abstraction bloat is one of those things that's a
| preference. What's bloat to one is organization to
| someone else. When I hope into a python codebase and it's
| 900 line file doing computer vision madness, I hope and
| pray for abstraction bloat. I'm sure there are countless
| c# bloated codebases but I think that's mostly a function
| of c# codebases being inside megacorporate or government
| codebases. The bloat comes from the general inefficiency
| that those companies run at. I guess the same could be
| said by the scrappy python startups that put everything
| in a single file with no types or inversion of control or
| OOP.
|
| I guess I'm saying that I'd rather deal with the bloat
| problem than the wild west problem. lol
| mattmanser wrote:
| C# doesn't really, but VS + the asp.net framework do.
|
| You kinda have to fight against the IDE to not do a lot
| of things a certain way. For example, it'll automatically
| namespace new files according to your folder structure.
| They've also turned a certain amount of automatic linting
| on to gently suggest/nag you to write in a particular
| way.Suggest you write classes in certain ways, use newer
| language features, declare variables in better ways, etc.
| You can ignore all the nagging, but it's also incredibly
| easy for the next programmer to walk in and use the quick
| actions functionality to 'fix' the code in a few clicks.
|
| And the asp.net core team have been incredibly
| opinionated, forcing a lot of good coding practices on
| the community.
|
| So on the plus side, they pretty much forced DI to be the
| way we all work now. It's worked really well. Most
| library authors have now embraced it with gusto and
| you'll have a hard time using new libraries in a code
| base that's DI incompatible.
|
| The bad side is that sometimes they made bad choices, but
| they are more minor things. Like they bizarrely went all
| in on JWT tokens which work really badly for corporate
| apps. Or the IOptions pattern for global settings which
| sucks compared to normal env variables in any other
| language. Lots of confusion over how they work on forums
| and SO.
| eterm wrote:
| Out of interest, what "patterns from the .NET framework
| era" do you think don't work well in .Net core?
|
| ( I'm someone who deals all day with legacy .Net
| framework projects, mixed with the kind of mix of .Net
| core 3, .Net 6, .net standard 2.0, and .Net 8 projects
| that you'd expect from a 20+ year old company with 260+
| projects. And yes, I too envy hobbyists at time. )
| djeastm wrote:
| >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've been spending the past couple years migrating
| various platforms from Framework to the new .NET and as
| long as you've got a head on your shoulders it's not too
| bad. Also, new projects in .NET are fantastic to work
| with, imo.
| progmetaldev wrote:
| I have been doing the same, but I would be willing to bet
| that you're probably more disciplined than the average
| .NET developer (or at least have taken the time to learn
| more than just the surface features available). In my
| experience, most .NET developers don't take the time to
| really learn the framework (whether traditional .NET
| Framework, or the Core framework). It is a great feeling
| once you've got a Framework project migrated over to
| current .NET and everything is running along smoothly. My
| experience has mostly been migrating content management
| systems.
| pipes wrote:
| Genuine question, what do you mean by "learn the
| framework" ? (I mainly work with c#, I constantly worry I
| am not proactive enough in my learning).
| progmetaldev wrote:
| I mean the built-in libraries for .NET (whether that is
| the older .NET Framework, or .NET Core - now labeled just
| as .NET). One of the biggest benefits to using C# and
| .NET is the amount of documentation available. If you are
| still using .NET Framework, and haven't moved to the
| open-source .NET, I would suggest spending some time
| learning the open-source version. It's not vastly
| different, and the good thing is the C# language hasn't
| changed very much, other than adding new features for
| developer ergonomics.
| steego wrote:
| Not to dismiss your criticisms, but I love that file
| ordering is relevant for compilation for one key reason:
|
| It forces you to reconcile your architecture as it gets
| bigger and before you accidentally turn it into a
| monolithic nightmare. IMO, It's more than just a preemptive
| defense against cyclomatic complexity. Going into
| unfamiliar F# code, the file ordering is usually a huge
| clue where to start reading first.
| GiorgioG wrote:
| Because 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.
| mlinhares wrote:
| C# 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 wrote:
| Come again?
| msk-lywenn wrote:
| This 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 wrote:
| I'd like a supported port of .NET to the BSDs.
| DaiPlusPlus wrote:
| > 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 wrote:
| Yeah, really. I'm distributing a .NET 8 app across Windows,
| macOS, Linux and x64/arm.
| Salgat wrote:
| Our developers write C# code using windows/mac/linux
| (it's up to their own preference) and we deploy to linux
| containers on AWS. Times have indeed changed.
| mlinhares wrote:
| Nah, people continue to pick Java or Go when they want to
| build their enterprise systems if they're not already
| married to Microsoft.
|
| There's not a single widely distributed infra application
| in C# out there. When people want to build stuff like
| kafkas, kubernetes, consuls, they still go to Java/Go/C++.
| lolinder wrote:
| This comment is kind of out of the blue because no one in
| this thread is advocating for using C# for infrastructure
| projects.
|
| Java is frankly a bad choice for that too these days for
| a new project, and for the same reason: why would you
| develop infrastructure in a language that requires
| shipping a runtime when Rust and Go exist? That made a
| lot more sense back when C/C++ was your only other real
| choice.
|
| Meanwhile, plenty of people are in this thread telling
| you that they do in fact use C# to distribute cross-
| platform applications, but you seem to be uninterested in
| hearing that.
| giancarlostoro wrote:
| It's even worse, plenty of Azure itself is C#, and I
| don't mean a few dashboards, I mean the infrastructure
| itself, heck the serverless infrastructure's open source
| and its basically C#. I'm sure the same could be said of
| AWS and Java (making an assumption), or Google Cloud
| Platform and Go / Python.
| pjmlp wrote:
| Ironically, given the past history that lead to .NET
| existence,
|
| https://devblogs.microsoft.com/java
|
| https://www.microsoft.com/openjdk
|
| https://code.visualstudio.com/docs/languages/java
|
| Because it turns out, making Java running on Azure, on
| those 60% Linux workloads, is lot of money.
|
| Also plenty of Azure, anything CNCF related, is mostly Go
| and Rust.
|
| Which is kind of sad, I would expect Azure to be a good
| contributor for having a .NET presence in the CNCF
| project landscape.
| giancarlostoro wrote:
| Fully agreed! It's really interesting how diverse their
| entire platform really is in the grand scheme of things.
| One thing I had hoped to see is one of those IL
| conversion projects that can make JVM bytecode and .NET
| bytecode co-habitate would have taken off slightly more.
| I guess the only real way to make those work is to either
| target both for WASM or implement the standard library of
| the respective languages in the target platforms, which
| is a can of worms.
| banashark wrote:
| Java has been fine for infrastructure projects. There is
| so much out there that relies on things like
| elasticsearch, Kafka, or any aws service. Heck even the
| columnar dbs like pinot and Druid are most likely more
| used than clickhouse.
|
| C# is also fine for this, just way less popular. Recently
| ms put out https://github.com/microsoft/Garnet when the
| redis debacle happened.
|
| The Apache project has helped put out quite a few large
| infra projects, most of them in Java (I don't know why
| this is but assume they have lots of resources to help
| with that, and also that people don't like debugging
| memory crashes).
|
| Ms has just been not the greatest collaborators with
| their open source community. A lot of the time it seems
| like they want to do the initial foundation, then leave
| "drawing the rest of the owl" to the community, which
| ends with lots of partially functional things. GUI
| frameworks, f# tooling, drivers for commonly used
| critical infra. At the same time, people get upset when
| ms tries to build a better version of an existing open
| source project, so there's no winning. They've just put
| themselves in such a poor spot.
| colonCapitalDee wrote:
| C# recently came out with Native AOT (ahead of time)
| compilation that compiles your app to a binary that can
| run without the .NET runtime (!!), and has fast startup
| and lower memory overhead. There are a few drawbacks:
| many reflection and run-time code generation and loading
| features are unavailable, and LINQ expressions must be
| interpreted which makes them slow. But it's easy to work
| around those limitations for a greenfield infra project,
| and C# has great performance characteristics.
| giancarlostoro wrote:
| > There's not a single widely distributed infra
| application in C# out there.
|
| Azure has entered the chat.
|
| Microsoft Orleans has entered the chat.
|
| ASP .NET Core has entered the chat.
|
| Ever played Halo online?
|
| Used StackOverflow? (very likely)
|
| Visited any website on Azure? (most likely)
|
| Microsoft Orleans (Virtual Actor framework) powers the
| Halo server infrastructure since at least 2011 if not
| sooner, which arguably the Halo series is insanely
| popular, especially for online gaming. Also powers plenty
| of Azure itselfs own infrastructure. I've worked on
| dozens of scalable C# projects, and know plenty of devs
| from all over who have as well.
|
| Orleans was so good, EA made their own version in Java
| which was extensively used there as well, though it looks
| to be dead, but Orleans is as alive as ever.
|
| Not to mention plenty of Azure itself is open source,
| like say... Azure Functions, which run inside of ASP .NET
| Web Services... and are... you guessed it, C#. Plenty of
| services running on that platform.
|
| https://github.com/Azure/azure-functions-host
| Fervicus wrote:
| I'll add Bitwarden and Jellyfin to the list of cross
| platform apps written in C# that are widely popular.
| viraptor wrote:
| And all the high seas software (sonarr, radarr, etc.)
| benbristow wrote:
| Bing is well known for being Microsoft's 'dogfood'
| candidate for new versions of .NET.
|
| https://visualstudiomagazine.com/articles/2018/08/22/bing
| -ne...
|
| https://www.bing.com/version
| 8338550bff96 wrote:
| A lot of devs are still living in the 2010s
| kldx wrote:
| https://isdotnetopen.com/
| metaltyphoon wrote:
| This always shows up. Comical.
| mattferderer wrote:
| A very common modern setup is PostgreSQL, C#/.NET, Linux &
| using JetBrains Rider for the IDE. You don't have to go all
| in Microsoft to use C#, F# or .NET.
|
| Also .NET has been about "run everywhere on any platform" as
| their tagline for quite a few years now.
|
| They have had plenty of community fumbles without question. I
| can't speak to those though. I've seen lots of vocal high up
| Microsoft employees try to win those fights on the side of
| the community but no idea what happens internally.
| CharlieDigital wrote:
| A very common modern setup is PostgreSQL, C#/.NET, Linux &
| using JetBrains Rider for the IDE
|
| You just described the startup I'm at. All devs are on
| Arm64 MacBooks and we deploy to Arm64 AWS T4g Linux
| instances. I'm all VS Code, others are primarily Rider.
|
| .NET is a highly underrated platform for backend; it always
| puzzles me when teams think about moving from TypeScript to
| Rust or Go instead of C# because it seems a much smaller
| leap from TypeScript.
| CBarkleyU wrote:
| I'm itching to try and deep dive into go as a C# dev. I'm
| getting sick of enterprise C#, even if it is .NET8
|
| I guess the grass is always greener somewhere
| HideousKojima wrote:
| Worst part for me about Go is how exceptions are usually
| basically handled the way that they would be with a
| Result<T> in Rust, but without an actual Result<T> type.
| That and how nulls are handled, feels like the worst of
| both worlds.
| CharlieDigital wrote:
| Maybe startup C# feels very different; it feels much more
| like TypeScript and I more or less write C# like I would
| write TypeScript.
| giancarlostoro wrote:
| For 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 wrote:
| C# 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 wrote:
| I use Python for real work too, but my current employer
| does not use it as much.
| paulddraper wrote:
| > 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 wrote:
| How 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 wrote:
| Well 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 wrote:
| That'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 wrote:
| But 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.
| bazoom42 wrote:
| Probably bescuse OOP was a great fit for desktop GUI's. This
| drove OOP into the mainstream. ML-style languages never had a
| similar killer application.
| munificent wrote:
| I think a similar but perhaps more accurate question is how
| did we prioritize virtual dispatch over ADTs?
|
| And I think the answer has a lot to do with the expression
| problem [1] and which kinds of extensibility were needed in
| the kinds of programs that languages at the time were
| designed for.
|
| OOP with subtyping and virtual dispatch makes it very easy to
| define an interface with a set of methods, and then have an
| open-ended set of concrete classes that all reliably
| implement those methods. It makes it easy to say "I don't
| know what data types I'll need yet, but I do know what
| operations I'll need."
|
| ADTs flip that around. That make it easy to express "I don't
| know what operations I'll need yet, but I do know what data
| types I'll need."
|
| For the kinds of simulations that Kristen Nygaard and Bjarne
| Stroustrup were writing, and then later the large GUI
| applications that C++ users were building, it seems that the
| former was more useful than the latter.
|
| [1]: https://journal.stuffwithstuff.com/2010/10/01/solving-
| the-ex...
| CharlieDigital wrote:
| It's possible to add DUs in C# today with some third party
| packages.
|
| - https://github.com/domn1995/dunet
|
| - 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-union...
| jeremycarter wrote:
| Actually not a bad solution. Thanks for sharing
| pseudopersonal wrote:
| You must really hate REPLs. You cling to your ADTs, I cling to
| my REPLs.
| indrora wrote:
| I can't speak to Rust but there have been plenty of C# repls
| in the past.
|
| https://fuqua.io/CSharpRepl/ For one
| maxbond wrote:
| I'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.
| tester756 wrote:
| I'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 wrote:
| I'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 wrote:
| If it wasn't so linux distribution unfriendly...
| nickcox wrote:
| In what ways?
| darby_nine wrote:
| > And _nothing_ gets even fucking close in terms of
| productivity to C#.
|
| C# gets compared to java a lot for a good reason, and yet the
| languages and ecosystems have since diverged in their
| priorities and abilities. This gets even more complicated
| when considering F# and Scala. Do you think Java would offer
| similar productivity, or are there aspects to the C# that are
| --in your personal experience--uniquely productive?
| Salgat wrote:
| The standard library alone is insane. The only time I need an
| outside library is for something specific like a database or
| sdk.
| foota wrote:
| I also really like rust's support for deriving traits. Being
| able to generate hashes, equality, debug strings, etc., is
| really convenient for hacking around.
| orra wrote:
| Is the terminology slightly off? AIUI TypeScript has type unions.
|
| But this looks like a discriminated union which I'd recognise
| from F# or Haskell. The distinction I'd draw is that for a DU
| there are named case constructors. Yes?
| wk_end wrote:
| TypeScript has "union types". This proposal refers to them as
| "ad hoc unions". I don't think "type union" is a term of the
| art - at least I haven't heard it before. It seems to be
| something the C# people are making up to describe sum types.
| SideburnsOfDoom wrote:
| > I don't think "type union" is a term of the art
|
| "sum type" is the term of art in Computer Science theory, but
| "union type" is also used.
|
| See
|
| https://en.wikipedia.org/wiki/Type_theory#Sum_type
|
| https://en.wikipedia.org/wiki/Tagged_union
| LandR wrote:
| Ha! Under covariance / contra variance
|
| > Note: Have Mads write this part.
|
| :)
| lyu07282 wrote:
| Mads Torgersen, lead designer of C#, just to clarify lol
| wackro wrote:
| What would the rough timeframe be for seeing adoption of this
| into the language?
|
| I was considering introducing the OneOf library into our
| codebase, but if this is < a year or so away it might not be
| worth the effort.
| leosanchez wrote:
| 3 years away at least.
| SideburnsOfDoom wrote:
| The linked says "Proposed, Prototype: Not Started,
| Implementation: Not Started, Specification: Not Started"
|
| .NET releases are every November, and I would be very surprised
| to see this in November 2024. More likely November 2025 at
| soonest. But check back to that page later.
| ygra wrote:
| Definitely no way for Nov 2024 since they're already no
| longer merging features for that release. Considering the
| scope of this, I'm doubtful for next year as well. .NET takes
| their time with features to get them right as well. They
| don't seem to take as long as Java, but maybe most new
| features are also not as widely publicized.
| louthy wrote:
| You won't be able to leverage C#'s pattern-matching effectively
| with a library.
|
| Really though, you don't need a library to do sum-types in C#:
|
| It's best to just use records for now: public
| abstract record Maybe<A> { private Maybe()
| { } public sealed record Just(A Value) :
| Maybe<A>; public sealed record Nothing : Maybe<A>;
| }
|
| The private constructor and sealed case-types stops anybody
| else deriving from `Maybe<A>`, so the type is effectively
| closed and finite.
|
| You can then construct like so: var mx = new
| Maybe<int>.Just(123); var my = new
| Maybe<int>.Nothing();
|
| Then you can use the pattern-matching: var r =
| mx switch { Maybe<int>.Just (var x) => x,
| Maybe<int>.Nothing => 0 };
|
| Of course, we don't get exhaustiveness checking, that'll have
| to wait for the proper sum-types (although the compiler does
| some pretty good work on this right now); but until then this
| is the most expressive and powerful way of doing sum-types in
| C#.
|
| And, if you want a load of pre-built ones, then my library
| language-ext will help [1]
|
| [1] https://github.com/louthy/language-ext/
| S04dKHzrKT wrote:
| Not quite closed. The compiler generated protected
| constructor can still be used. public
| record UhOh<A> : Maybe<A> { public UhOh()
| : base(new Maybe<A>.Nothing()) { }
| } Maybe<int> m = new UhOh<int>();
| owisd wrote:
| It's a different kind of ugly, but you can use the Visitor
| pattern to get the same exhaustiveness checking at compile time
| without a library.
| CrimsonCape wrote:
| It's not a bad idea to evaluate OneOf. This proposal relies on
| records, so every use instance requires heap allocations and
| dereferencing which has memory and time implications
| respectively.
|
| I implemented my own option types entirely differently via ref
| structs where the "non-option" becomes either a default of a
| value type or a null reference (size of a pointer). Then (in
| theory) the overhead is reduced to a single dereference with
| everything else being stack-allocated.
|
| I then built the same thing as a non ref (regular) struct
| version for storing in a field. So I have Options.Quick and
| Options.Long namespaces with practically the same struct design
| just the former is a ref struct.
|
| This has served me very well, is very fast. It just doesn't
| have the exhaustive checking and risks derefing a null
| reference, but in practice is not a big issue.
| if(option.IsT1){ doSomething(option.ValueT1)};
| if(option.IsT1){doSomething(option.ValueT2)}; // this would
| throw an exception, i.e. a bug, but its very readable to catch
| the bug
| ctenb wrote:
| I find it strange and slightly confusing that tey call it "union
| types". The correct term would be "sum types" or "discriminated
| union types", union types being the union of two types with no
| distinctive tag between the two cases. E.g. |Int [?] Int| [?]
| |Int|, while |Int + Int| [?] 2 |Int|
| lolinder wrote:
| > I find it strange and slightly confusing that tey call it
| "union types". The correct term would be "sum types" or
| "discriminated union types"...
|
| You mean like this?
|
| > A proposal for type unions (aka discriminated unions) in C#.
|
| Discriminated unions are a type of union type, hence the name,
| and in terms of how they're used in everyday development they
| fill a very similar role. If they have no intention of
| supporting pure TypeScript-style unions (which I'm sure they
| don't) then I don't know what the harm is of shortening
| "discriminated union" to "union" in the context of C#.
| ctenb wrote:
| I've read the proposal, and I'm just pointing out that "aka
| discriminated unions" is incorrect or at the very least
| confusing. Call it "sum types" if you don't like the term
| "discriminated union types", it's both correcter and shorter
| than "union types"
| noelwelsh wrote:
| AFAICT from a quick skim of the proposal is actually includes
| both sum types (called union types) and union types (called ad
| hoc unions) under the same proposal. This is, to me, very
| confusing. They work in very different ways.
| jsmith45 wrote:
| At runtime every value of any of these types are tagged in
| some some way. The struct based ones with an explicit tag
| member that is not visible at the language level. All the
| rest by way of the object's runtime type (v-pointer).
|
| Which means the fact that some look at a language level like
| a traditional closed sum type, and others look more like a
| union type is pretty much just that, looks. Even the "ad hoc
| unions" are basically functioning as sum types here, just an
| ad hoc sum type whose type constructors are other types, and
| abusing the fact that classes or boxed structs all have a
| vptr that can be used as the discriminator.
|
| This all compiles down to code that pattern matches on either
| the explicit tag member, or on the runtime type, and after
| the pattern match you basically have a normal type to work
| with. Hence why they are lumping it all together.
| munificent wrote:
| The proposal does both sum types and union types.
| ctenb wrote:
| I'm currently using nested records with a private constructor in
| combination with the nuget package
| https://github.com/shuebner/ClosedTypeHierarchyDiagnosticSup...
| to make sure the switch types do not require a `_` case. This is
| essentially the desugared version of their "Union Classes"
| proposal. This already works very well. Still, I like this
| proposal because it would be nice if the nuget package would
| become unnecessary and the syntactic sugar is also nice to have.
| S04dKHzrKT wrote:
| Do note that record types aren't closed even with a private
| constructor. The compiler will generate a protected constructor
| for copy operations which can then be inherited from. To
| prevent this, you have to define your own protected constructor
| and have it throw a runtime exception if it isn't a valid case.
| ctenb wrote:
| You are technically correct (the best kind of correct), but
| in practice I've not found this to be a problem, certainly
| not something that is ofsetting the vast usefulness of this
| data pattern.
| S04dKHzrKT wrote:
| I've found the same to be true as well.
| Alifatisk wrote:
| Even dotnet is looking at implementing type unions, why can't
| Dart finally agree on adding this aswell!?
| munificent wrote:
| We added sum types and exhaustive pattern matching in Dart 3.0.
|
| Union types (what the proposal here calls "ad hoc unions") are
| a separate, much harder feature whose value proposition is less
| clear. The cost of adding a new kind to the type system is
| quite large because it impacts method resolution, overriding,
| type inference, subtyping, least upper bound, generics, type
| promotion, etc.
|
| It can be worth it (for example, we added tuple/record types in
| Dart 3.0), but the value proposition must be correspondingly
| high to justify it. It's not clear that union types meet that
| bar yet. In many if not most of the places where users are
| asking for it, it often seems like what they really want is
| overloading or some other feature.
| tubthumper8 wrote:
| Can anyone explain why this is called "type unions"? I've never
| heard it named that before. It's a bit weird, because it's not a
| union across types (like ALGOL68), it appears to be a tagged
| union like in ML-family languages.
|
| Is this just a case of "C# developers like to make up different
| names than established terminology"? (see: SelectMany,
| IEnumerable, etc.)
| kgeist wrote:
| "Tagged" sounds like an implementation detail to me (that it
| has a "tag" internally to tell between types). I suspect they
| added "type" to "union" to make it clear what is about (about
| types). The syntax itself has just "union", judging by the
| document.
|
| UPD. They have this in the FAQ: Q: Why are
| there no tagged unions? A: Union structs are both tagged
| unions and type unions. Under the hood, a union struct is a
| tagged union, even exposing an enum property that is the tag to
| enable faster compiler generated code, but in the language it
| is presented as a type union to allow you to interact with it
| in familiar ways, like type tests, casts and pattern matching.
| LAC-Tech wrote:
| I always think it's a shame that instead of C# becoming a better
| OO language, they keep trying to become an uglier F#. IE, why is
| the syntax for multiple dispatch still so clunky?
|
| I know I know, pseudo OO took over the world, and then people
| revolted against it, so the easiest thing to do to stay relevant
| is to become "slightly functional with curly braces", rather than
| to actually try and do OO well.
| mrkeen wrote:
| I have the same objection but coming from the other side. The
| mainstream languages used to have pervasive mutation and side-
| effects. Now they have pervasive mutation and side-effects with
| lambdas.
|
| But my question is: what is missing from the OO side? What
| would it take for C# and/or others to "do OO well"?
| LAC-Tech wrote:
| To be clear I don't really come from "the other side". I very
| much enjoy and like functional programming. But again, that's
| what F# is for, right? If we push the state of the art in
| another directrion, the whole landscape benefits more -
| because I think we both agree C# is never going to be a
| better FP language than F#.
|
| As for what C# could do better, the OO solution to the
| problem pattern matching solves is multiple dispatch - with
| single dispatch languages you need things like the visitor
| pattern. Making that a first class part of C# would be
| fantastic.
|
| https://shawnhargreaves.com/blog/visitor-and-multiple-
| dispat...
| lyu07282 wrote:
| > What would it take for C# and/or others to "do OO well"?
|
| Multiple inheritance. (j/k)
| LAC-Tech wrote:
| Unironically this.
|
| Having "interfaces" and "abstract classes" is just a
| kludge, multiple inheritance covers all of this with one
| language construct.
|
| The "diamond problem" is a C++ issue, every other language
| solved it.
| tester756 wrote:
| What does "better OO" mean here?
|
| Which concepts or feature you have on mind?
| pipeline_peak wrote:
| It's ironic when things like this get added back into C-styled
| languages that were intended to be easier than their
| predecessors.
|
| Seems more confusing than useful. Wish they'd stop adding onto
| this ever expanding language.
|
| It's like these people get bored of plain old functions and
| objects, read an academic paper and go "i think I'll add that
| next".
| riizade wrote:
| I don't have anything insightful to add, I just want to add my
| voice to the choir of people saying that after using sum types,
| working in a language without them feels unnecessarily
| restrictive and awkward.
|
| If this feature were implemented, it would take C# to a top
| contender for a daily driver language for me, and would make me
| feel a lot more confident in choosing it for projects where the
| C# ecosystem is already present, such Godot's C# version.
|
| I'm really excited about this proposal, and I don't know anything
| about C#'s development pace, but I'll be watching from the
| sidelines hoping I can use union types in production in 2025 or
| so.
___________________________________________________________________
(page generated 2024-08-07 23:00 UTC)