6 ms·
For a lot of stuff what I really want is golang but with better generics and result/error/enum handling like rust.
by dmoy 10mo ago
For a lot of stuff what I really want is golang but with better generics and result/error/enum handling like rust.
- mixedCase 10mo agoOCaml is the closest match I'm aware of.
- evanmoran 10mo agoI thought the recent error proposal was quite interesting even if it didn't go through: https://github.com/golang/go/issues/71528 https://github.com/golang/go/issues/71528 My hope is they will see these repeated pain points and find something that fits the error/result/enum issues people have. (Generics will be harder, I think)
- Rikudou 10mo agoDidn't they say they're not accepting any new proposals for error handling? I kinda got used to it eventually, but I'll never ever consider not having enums a good thing.
- pa7ch 10mo agoI was a big fan of the original check handle proposal: https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md https://go.googlesource.com/proposal/+/master/design/go2draf... I see the desire to avoid mucking with control flow so much but something about check/handle just seemed so elegant to me in semi-complex error flows. I might be the only one who would have preferred that over accepting generics. I can't remember at this point because there were so many similar proposals but I think there was a further iteration of check/handle that I liked better possibly but i'm obviously not invested anymore.
- throwaway894345 10mo agoI cautiously agree, with the caveat that while I thought I would really like Rust's error handling, it has been painful in practice. I'm sure I'm holding it wrong, but so far I have tried: * thiserror: I spend ridiculous and unpredictable amounts of time debugging macro expansions * manually implementing `Error`, `From`, etc traits: I spend ridiculous though predictable amounts of time implementing traits (maybe LLMs fix this?) * anyhow: this gets things done, but I'm told not to expose these errors in my public API Beyond these concerns, I also don't love enums for errors because it means adding any new error type will be a breaking change. I don't love the idea of committing to that, but maybe I'm overthinking? And when I ask these questions to various Rust people, I often get conflicting answers and no one seems to be able to speak with the authority of canon on the subject. Maybe some of these questions have been answered in the Rust Book since I last read it? By contrast, I just wrap Go errors with `fmt.Errorf("opening file `%s`: %w", filePath, err)` and handle any special error cases with `errors.As()` and similar and move on with life. It maybe doesn't feel _elegant_, but it lets me get stuff done.
- thijsr 10mo ago> I also don't love enums for errors because it means adding any new error type will be a breaking change You can annotate your error enum with #[non_exhaustive], then it will not be a breaking change if you add a new variant. Effectively, you enforce that anybody doing a match on the enum must implement the "default" case, i.e. that nothing matches.
- Yoric 10mo agoFWIW `fmt.Errorf("opening file %s: %w", filePath, err)` is pretty much equivalent to calling `err.with_context(|| format!("opening file {}", path))?` with anyhow. What `thiserror` or manually implementing `Error` buys you is the ability to actually do something about higher-level errors. In Rust design, not doing so in a public facing API is indeed considered bad practice. In Go, nobody seems to care about that, which of course makes code easier to write, but catching errors quickly becomes stringly typed. Yes, it's possible to do it correctly in Go, but it's ridiculously complicated, and I don't think I've ever seen any third-party library do it correctly. That being said, I agree that manually implementing `Error` in Rust is way too time-consuming. There's also the added complexity of having to use a third-party crate to do what feels like basic functionality of error-handling. I haven't encountered problems with `thiserror` yet. > Beyond these concerns, I also don't love enums for errors because it means adding any new error type will be a breaking change. I don't love the idea of committing to that, but maybe I'm overthinking? If you wish to make sure it's not a breaking change, mark your enum as `#[non_exhaustive]`. Not terribly elegant, but that's exactly what this is for. Hope it helped a bit :)
- dmoy 10mo ago> In Rust design, not doing so in a public facing API is indeed considered bad practice. In Go, nobody seems to care about that, which of course makes code easier to write, but catching errors quickly becomes stringly typed. Yes, it's possible to do it correctly in Go, but it's ridiculously complicated, and I don't think I've ever seen any third-party library do it correctly. Yea this is exactly what I'm talking about. It's doable in golang, but it's a little bit of an obfuscated pain, few people do it, and it's easy to mess up. And yes on the flip side it's annoying to exhaustively check all types of errors, but a lot of the times that matters. Or at least you need an explicit categorization that translates errors from some dep into retryable vs not, SLO burning vs not, surfaced to the user vs not, etc. In golang the tendency is to just slap a "if err != nil { return nil, fmt.Errorf" forward in there. Maybe someone thinks to check for certain cases of upstream error, but it's reaaaallly easy to forget one or two.
- Yoric 10mo agoHave you tried OCaml? With the latest versions, it also has an insanely powerful concurrency model. As far as I understand (I haven't looked at the benchmarks myself), it's also performance-competitive with Go.
- throwaway894345 10mo agoHow's the build tooling these days? Last I tried, it used some jbuild/dune + makefiles thing that was really painful to get up and running. Also there were multiple standard libraries and (IIRC) async runtimes that wouldn't play nicely together. The syntax and custom operators was also a thing that I could not stop stubbing my toes on--while I previously thought syntax was a relatively unimportant concern, my experience with OCaml changed my mind. :) Also, at least at the time, the community was really hostile, but that was true of C++, Ada, and Java communities as well well. But I think those guys have chilled out, so maybe OCaml has too?
- Yoric 10mo agoI'm re-discovering OCaml these days after an OCaml burnout quite a few years ago, courtesy of my then employer, so I'm afraid I can't answer these questions reliably :/ So far, I like what I've seen.
- myaccountonhn 10mo agoOcaml community is chill and helpful, and dune works great with really good compilation speeds. Its a really nice language
- yawaramin 10mo ago$ dune init project my-project $ dune build That's it, now you have a compiling project and can start hacking.
- zozbot234 10mo agoThere's also ReasonML if you want an OCaml with curly braces like C. But both are notably missing the high-performance concurrent GC that ships with Golang out of the box.
- Philpax 10mo agoYou want https://github.com/borgo-lang/borgo https://github.com/borgo-lang/borgo, but that project is dead. You might be interested in Gleam?
- scythmic_waves 10mo agoBorgo [1] is basically that. Though I think it's more of a hobby language. The last commit was > 1 year ago. [1] https://news.ycombinator.com/item?id=40211891 https://news.ycombinator.com/item?id=40211891
- oncallthrow 10mo ago[flagged]
- vips7L 10mo agoMe too. There’s a huge market for a natively compiled language with GC that has a better type system than Go. The options I’ve seen so far are: OCaml, D, Swift, Nim, Crystal, but none of them have seen to be able to capture a significant market.
- metaltyphoon 10mo agoC#?
- gf000 10mo agoAlso Haskell, Java, Kotlin, Scala, OCaml, D, and the list goes on.
- metaltyphoon 10mo agoOut of all those only Java and Kotlin captured significant market like OP mentioned
- vips7L 10mo agoThose two aren’t natively compiled. They can be, but it’s not the norm, and it’s hard/time consuming. Java’s type system isn’t as strong as it could be either. It is still lacking proper compile time support for null and there’s been no investment in making error handling better. I’ve written it every day for 10 years and the type system definitely doesn’t help you write correct programs.
- gf000 10mo agoCompared to what? Because compared to go which has not one but 2 nulls, and an even more anemic type system it is surely much better. > the type system definitely doesn’t help you write correct programs. It surely helps significantly. You are just looking for even more from the type system, but that's another (fair) statement to make.
- hgs3 10mo agoAre you familiar with Zig's error handling? It's arguably more Go-like than the Rust approach.
- gf000 10mo agoNo, Zig's error handling is decent - you either return an error or a value and you have some syntactic sugar to handle it. It's pretty cool, especially given the language's low-level domain. Meanwhile Go's is just multiple value-returns with no checks whatsoever and you can return both a valid value and an error.
- beautron 10mo agoBut sometimes it is useful to return both a value and a non-nil error. There might be partial results that you can still do things with despite hitting an error. Or the result value might be information that is useful with or without an error (like how Go's ubiquitous io.Writer interface returns the number of bytes written along with any error encountered). I appreciate that Go tends to avoid making limiting assumptions about what I might want to do with it (such as assuming I don't want to return a value whenever I return a non-nil error). I like that Go has simple, flexible primitives that I can assemble how I want.
- gf000 10mo agoThen just return a value representing what you want, instead of breaking a convention and hacking something and hoping that at use site someone else has read the comment. Also, just let the use site pass in (out variable, pointer, mutable object, whatever your language has) something to store partial results.
- Orygin 10mo ago> instead of breaking a convention and hacking something and hoping It's not a convention in Go, so it's not breaking any expectations
- 10mo ago
- qudat 10mo agoI think generics ruined the language. Zig doesn’t have them
- gf000 10mo agoBut it has something for it (compile time evaluation of functions).
- sylens 10mo agoClosest is probably C# but its still primarily an OOP driven language
- mrsmrtss 10mo agoI would say, C# supports more functional programming than Go. Go is more imperative than a functional language.