HACKER Q&A
📣 losvedir

What's the best “higher level Rust” these days?


After playing with rust, I really like it. However, I generally don't need to write the low level code that justifies the increased complexity of the borrow checker. I would rather just pay the small price for a garbage collector. What language is most like rust, but at a higher level?

To me, these are the things that I like about rust that I'd want to see:

* Getting nullability right, not making the "billion dollar mistake". An integer shouldn't be able to be "null" unless it's part of the type.

* "Algebraic" (Sum and Product) data types. I love Typescript's "integer | null" syntax, but Option or something like that is fine, too. Typed structs/records or tuples.

* Errors as values. Goes naturally with the ADTs, and it feels very robust having the compiler enforce handling all the "Ok(..) | Err(..)" results.

* Focus on the data, defining structs and functions that work with structs. "Traits" as a means of abstraction. Not much in the way of inheritance.

* A nice development experience with a good package manager or other way of finding and using open source code.

* Vibrant and growing community.

* Can develop comfortably on Mac, deploy to Linux. Windows support a "nice to have".

Rust just nails all these things so well, it makes me want to use it even for things that don't seem like a good fit to me, like command line tools or web servers or scripts.

Here are the languages I can think of that might work, but I think they all have some issues:

* Ocaml - Rust's heritage, so it makes sense. But I feel like it's been around forever and hasn't really taken off. And doesn't it still have some sort of concurrency issue?

* Swift - So close to the ideal language, but does it work well outside of the Mac ecosystem?

* F# - Conversely, another great language, but does it work well outside of Windows?

* Java - The last time I used Java in earnest (many, many years ago) it still had the nullability issue, and was too class/inheritance focused for my tastes. I'm not sure if modern Java has improved on this yet.

* Typescript - Is this it? As a language, it actually ticks all the boxes, I think, which surprises me. But as a runtime it's nonexistent, and so you have to compile to Javascript and run on node and all that. I use it and really like it on the frontend. But how is it on the backend for ordinary non-web applications? How's its performance? It feels fiddly to get all the build stuff running, but maybe Deno or Bun is an option here.

* Nim - Kind of off the wall here, but it looks like it might actually be a contender from perusing its docs. But its community is pretty niche, and I don't have a good sense on if its growing or not.


  👤 kitsunesoba Accepted Answer ✓
I’m not sure that any language meets these criteria yet, but I’m placing my bets on Swift. There’s been a lot of activity in Swift’s various cross-platform working groups recently… whether or not that pans out remains to be seen, but within the community there’s absolutely a desire/will for Swift’s cross platform story to improve.

Personally speaking, if Swift’s Windows/Linux support improved and a cross platform UI framework were built for it, I’d have a hard time imagining using anything else for cross platform desktop development. Swift gets a lot right for that use case and strikes a good balance between ergonomics and safety.


👤 elcritch
Personally, Nim fits a sweet spot for me. It has most of the items you listed, and makes a lot of projects interesting to me much more fun to program. It makes writing CLI utils and quick data migration scripts easy and fun. I use it for embedded software for the great balance of productivity vs performance.

I’ve been working to build more libraries and community for embedded software. It’s been slow going but a couple of companies are using it in shipping products. Nim leverages existing C code very well though.

Though Nim does have its downsides, primarily a smaller community. It’s small but active and not going away anytime soon. I think the ecosystem is slowly building a solid foundation of core libraries since the language reached 1.0 and found its feature set. But it doesn’t have a “killer” feature or single library to drive it. So hopefully the slow and steady buildup can keep going. For example, one big investor in Nim ecosystem for example just hired someone to work full time on the language server / tooling. There’s more work going on with numerical processing too (eg native graphing libraries, etc).

For me in many areas the language more than makes up for the smaller community. I can wrap C/C++ libraries quickly and I don’t need to do borrow checker. Though I would say it sounds like Go or Swift might fit some of your preferences too. Rust is great in many ways but I am more productive with “compile time duck typing” while Rust favors traits and fixed predefined abstractions.


👤 kurtbuilds
I'd recommend going full steam ahead with Rust.

Companies like Azure and Meta now recommend Rust as either one of several viable choices, or THE recommended option, for the use cases you describe, including CLI and web servers.

Personally at this point, just about anything that's not a frontend (android, ios, web), I think Rust is the best language for the job. It's the language I prefer, and feel most productive in, for the use cases you're describing (web server, CLI, small scripts and utils).

There's a learning curve, but at this point, I almost entirely forget about the lack of GC. It feels like writing code in any other language - except of course with all the benefits you call out (no null, ADT, typed error values, trait-based OO system, the best tooling of any language I've used, expansive 3rd party libraries).


👤 DemocracyFTW2
I can't really directly answer your question as I'm looking for pretty much the same—a language like Rust, just easier to use. I could imagine that being a language that transpiles to Rust so I sometimes head over to https://lib.rs to see what's new in the space.

Other than that I'm these days only mildly interested in languages that do not compile to WASM or transpile to JS because NodeJS and the browser have become my main platforms. IMO browsers offer an unprecedented way to develop GUIs for applications. People are unhappy with the perceived bloat of it but there's a web browser on almost each single consumer-facing (i.e. non-backend / server) machine these days and those things have become very, very capable. I just feel deprived of something when I go back to, say, Python.

I'm not very interested in TypeScript anymore b/c for the troubles and the benefits that typing gives you I want to have a solution that works at run time and ideally at compile time, too—I'd rather forgo the latter but not the first b/c of user input validation. Having to entertain that whole fancy and complex beast that is a good type system only to not be able to use it for run time checks is not what I want.

Just a few thoughts.


👤 jmfldn
Scala

* Getting nullability right - Tick.

* "Algebraic" (Sum and Product) data types. Tick.

* Errors as values - Tick.

* Focus on the data - Tick.

* A nice development experience - Tick (has got a lot better in recent years).

* Vibrant and growing community - Tick. Hard to know if it's growing, but it feels like it has a very stable niche imho. I see a lot of dynamism in the communities I follow like Typelevel.

* Can develop comfortably on Mac, deploy to Linux. Windows support a "nice to have. Tick. I've developed on all of these environments.

Is it a "higher level Rust?". It's a very different beast but, based on your checklist at least, it fits the items them than most other mainstream languages imho.


👤 hedora
Have you tried wrapping everything in an Rc<> (or Arc>) and keeping everything synchronous and single threaded? I've seen people report good success with that for low-performance stuff.

Reference counted languages provide 99% of the benefit of full GCs for simple programs, and I think those two suggestions are enough to mindlessly appease the borrow checker in most circumstances.


👤 pie_flavor
C#/F# being Windows languages is plain false; they have been cross-platform FOSS for just under a decade. TypeScript has a good number of features you're talking about, but I still wouldn't use it myself, because it is only a static checker on top of a much worse underlying system, and the static checker has plenty of holes big enough to fit serious problems through. Your best option as far as I can tell is Swift. It checks all the boxes, and in fact cribs quite a bit directly from Rust; its package repository is serviceable, if light on more niche use-cases; and it has supported Linux for quite some time, and recently started supporting Windows (though not the package manager, so not really).

But if Windows support is more important than a little bit of cognitive overhead? Just stick with Rust. It works, it's all the good things with few of the bad, it's more maintainable than anything mentioned, and the best language to write anything in is the language you already know.


👤 syzygyhack
Nim is a great language with some killer features, but if the community is growing, it's doing it very slowly.

TypeScript would have my vote. I have my eye on Deno and Bun but they aren't there yet, Node gets the job done every time.


👤 angelmunoz
I learned F# before I took a dive at rust, while I don't have use cases for rust on my day to day I think these two languages are very similar and you can fare a very long way with what you already know from rust it is worth taking a look at it

F# is cross-platform with excellent tooling from vscode via ionide extension, jetbrains rider, and visual studio, it also ticks several boxes from above :)

Feel free to chime in twitter there's the #fsharp hashtag, The F# Org slack https://fsharp.org/guides/slack/ and the unnoficial F# discord server https://discord.com/servers/fsharp-196693847965696000


👤 belmont_sup
Unfortunately I have to agree with your inner voice that there's no perfect language out there.

I'm building my first library in OCaml for a number of great reasons: 1. the type system we all want 2. multicore is here (but in RC) 3. algebraic effects is here (but in basically RC) 4. build system is pretty good after you warm yourself up a bit. i ran into some weird dep issues recently but overcame it by vendoring deps directly.

A hard requirement for me is to be able to generate native executables, and only OCaml / Rust / Swift has this with a more modern type system. If I wasn't so focused on learning in an fp language, I'd use Rust for my needs.

If you asked for a vote, I'd say give 2 weeks for each of your top 3 languages. Opinions and anecdotal experience will always be beaten by personal experience.


👤 xd1936
You might like running Typescript on Deno[1].

1. https://deno.land/


👤 schrodingerscow
IMHO swift has one of the most beautiful type systems and is more high level than rust. Of course youre limited on what platforms you can use it with but server side swift is getting a lot more attention. Kotlin is pretty comparable though so maybe that’s your best bet. Haskell is also great but if you want the slightly more imperative style then I think kotlin or swift are the best fits. I find all to be the times I have the most fun programming. You can also get part of the way there with typescript and the fp-Ts ecosystem but of course the type system has a lot less overlap with rust

👤 jonfw
Golang is continuing to grow to serve this use case. Just like explicitly handling errors though- you'd be expected to explicitly handle null values if you want to be safe from them

👤 jstx1
> However, I generally don't need to write the low level code that justifies the increased complexity of the borrow checker.

Your criteria are so specific that it will be easier to just learn how the borrow checker works.


👤 rowanG077
In my dayjob I use Haskell + Rust and in many ways I feel like Haskell is a higher level Rust.

👤 akkad33
F# is not a windows language. It's been open source from the start and there are many compiler implementations that does not depend on Windows at all, like Fable.

That said I think it has many parallels with Rust and I enjoyed reading this comparison between the two https://github.com/Dhghomon/rust-fsharp

It shows how strikingly similar the two languages are, at least on the surface.


👤 freemint
I would recommend taking a look at Julia. What it can't do is "get nullability right at compile time" however you can define Integer values which can't be zero and have that changed at run time with more and more of these checks moving to compile time but still raising errors at run time, "force you to look at values" but you can throw arbitrary stuff which is nice. Julia has the rest you wish for though. Julia has nice macros, has multiple dispatch instead of inheritance, a vibrant and growing community. It is mostly used in numerical work however use it on other domains has also shown a lot of promise, at the moment producing standalone binaries is still complicated, it pays compile time every time a function is called with new types.

👤 mlindner
> After playing with rust, I really like it. However, I generally don't need to write the low level code that justifies the increased complexity of the borrow checker. I would rather just pay the small price for a garbage collector. What language is most like rust, but at a higher level?

I think you've mixed yourself up somewhere here. A garbage collector doesn't protect you from stale references, it just makes sure that it results in a program crash (or exception of some sort) rather than letting your program run off into fantasy lands where pigs fly and everyone casts magic spells. Rust still protects you by turning these errors into compile time errors, saving debugging time.


👤 steveklabnik
Some related thoughts (from 2019) from someone who was part of the language team: https://without.boats/blog/notes-on-a-smaller-rust/

👤 blueslurpee
Nice thread. The comment about "full steam ahead with Rust" was nice.

Like you I've been on a basically identical search, but instead of coming up from Rust I've come down from dynamically typed languages on the backend. I just couldn't bear another run-time error that would have been easily prevented with Typescript.

I've come to the conclusion that the palette of ergonomic and statically typed languages for the backend is surprisingly quite sparse (when one includes the requirement of a relatively sizable community) if you don't include Java/Go.

Languages I personally crossed off:

* Java - Just much too verbose for my taste, too mutable, too nullable, and I don't find "Kingdom of Nouns" elegant to program in. (The JVM is quite magnificent though..)

* Golang - I get why people like it, and I have absolutely nothing against it. For me it's not expressive enough.

* Typescript - Pretty much 100% what you said. The language itself is wonderful, but it really shines when confined to the browser. The runtime differences between the Browser/Node cause all sorts of problems. Also compiled binaries are nice, which are out here.

I see why somebody might choose each of those languages, and be highly justified in doing so, but for me they didn't fit the bill.

That leaves:

* Scala - Only have very light experience. Really strong support for functional/immutable style programming, and checks all the boxes as another commenter pointed out. Community seems a bit complex at times. I haven't had time to really dive into it, but it's been on my mind.

* Rust - Seems like it nails a lot of things really well. Haven't ever touched it, so I can't give an educated appraisal of its merits. The only real obvious con is that it's "overkill" for systems dealing primarily with business logic, i.e. where GC isn't a big issue.

* Swift - Seems quite excellent, but I had written it off as unsuitable for general purpose stuff. Perhaps a premature take?

* Nim - The one on the list I have played around with the most. Seems to have a very powerful macro system which I have yet to take full advantage of. Feels like a statically-typed python, with a bent towards an imperative style over a more functional one. I am personally thrilled they went with the decision to make "func" a fist-class keyword, with special compiler significance. Still a bit niche however.


👤 birdfood
Bit left field, but I think Haxe is a good "higher level rust".

* It's garbage collected

* Has algebraic types (enums similar to rust's)

* Pattern matching as good as rust's

* Null check strictness can be configured with the compiler

* Package manager

It's somewhat OOP geared though.


👤 spookierookie
How about crystal?

https://crystal-lang.org/


👤 jryb
Honestly it sounds like you should stick with Rust a while longer, until those low level things no longer present an obstacle. I've finally gone all-in on Rust and after a few months of full-time use at work I feel like I've "broken through" to the same level of productivity I had with Python (which I've used for a decade).

👤 llanowarelves
Last I used Deno it was about half the speed of Node.

👤 majormunky
Have you looked at Zig? Can’t say if it ticks all the boxes but it looks like a pretty interesting language.

👤 amir734jj
C# is a good option.

F# if you want functional C#.

Scala if you are adventurous.