Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

Is Rust a high-level language or a low-level language? Does rustlang's development prove you don't have to choose? My impression of Rust is that it's intended to replace C/C++, and that web frameworks are high-level libraries (whereas something like an HTTP library would be low-level). I guess you could write a web framework in C/C++ but I don't know of any that are popular or widely used off the top of my head. IIRC I think golang was meant to be low-level, but the community mostly came from high-level scripting languages that saw a visible boost in performance.

Congratulations to the authors/contributors of actix-web on the 1.0 release!



view as:

In my experience it has elements of both, but stuff like managing lifetimes means that (IMO) it's more trouble than it's worth when you're creating a web backend. Any more established garbage collected language is absolutely fine. Unless it needs to, say, run in a very resource constrained environment, in which case it's a pretty interesting possibility.

It's certainly a less mature ecosystem, but once you get over the hump of understanding lifetimes, there's nothing preventing you from using lots of owned values and clone in a way that makes it really easy to ignore annoying lifetime problems. And, the benefit being if you ever need to get more performance out of a hot part of your code, you can always optimize to get that zero copy goodness.

There is however a downside to the „clone everything“ approach: The performance might get worse than what it would be in an optimized GCed language that doesn’t require cloning (eg C#/Java).

At least I would only reach out for Rust at the moment for performance critical code, and then don’t leave easy optimizations on the table due to lifetimes.


There are other solutions (like Rc<RefCell<T>>) that allow you to avoid cloning as well if you still don't want to deal with lifetimes.

Rust's lifetimes make it about the only language that gets shared-memory concurrency right. And I don't like the trend of pushing for message passing just because historically it was hard to do shared memory. The only thing I've found more convenient than that was software transactional memory in Haskell (monads and do notation working with it barely different than regular mutable memory), maybe by the next 10 years or so we'll get that in a mainstream language.

To add to the STM conversation, the stm-containers libraries is insanely cool (& performing with high concurrent access!)

Lifetime issues are not really relevant in a classic web backend context, since you generally just pull data out of a DB and return it to a web request, or the other way around. You generally don't have to share you data structures.

I do agree though that the tooling is very immature compared to other ecosystems, and Rust is generally quite boilerplate heavy and slower to develop.

It can still be a good choice if you need really high performance/low resource consumption - or you are going for high correctness and robust error handling.

But for most web backends Rust won't make much sense.

(I say this as someone who even writes web frontends with Rust via wasm, where it is even less optimal - mainly due to the high compile times)


Do you have any examples of the sort of front end work your doing with Rust? I've been toying with an idea using Rust but I haven't started really working on it.

Not any language have such smart compiler, perfect errors handling system, "cargo" crates system. Not in every language refactoring is so nice that you can do it absolutely without fear.

I see web frameworks like this as being useful to expose an IPC/RPC service layer into a low-level component.

If you’ve noticed that lately there are a lot more pieces of systems software built in the architecture of “a daemon plus a client executable that talks to it over a control-channel Unix domain socket, but where that same control-channel [with different auth logic] can also be exposed over the Internet” — that’s thanks mostly to people writing things in Go, and Go making that architecture easy to set up (with the simplest option being a gRPC-protocol connection, but a RESTful HTTP service layer being only a little bit more work.)

Now it’s easy to set up such a RESTful service layer for your daemon in Rust, too!


It's both high-level and low-level. It can go all the way down to bare metal. actix-web abstracts away so much complexity that it's possible to program high-level tasks and be productive, but eventually work will require Rust expertise. In my first year with Rust, I accomplished a lot by using the high-level actix-web api and learning the language as I went along. I still have a lot more to learn. For instance, I can't write low-level network Connectors required of 3rd party clients (for instance, redis). Community can only help answer so many questions. It's important to develop competencies and achieve self-sufficiency (easier said than done).

It's intended to be both.

Coming from mostly a web programming background, it certainly feels more low-level than PHP/JavaScript, but not by much, at least for web/backend work. You can still code without having to delve into low-level/unsafe coding, but that stuff is available to you if you need to squeeze more performance out of your app.

The biggest hurdles for me (I'm still learning) compared to JS is the borrow checker, lifetimes, and strings (they are handled very precisely in Rust).

The benefits are huge though. My time coding in JS feels like 50% coding & writing tests, 40% debugging my app, 10% reading documentation. The "debugging" portion can sometimes be painful when fixing race conditions. Rust on the other hand, feels like 30% reading documentation, 30% coding, 30% getting my code to compile, and the other 10% debugging/testing my app. For the most part, if your code compiles and your logic is correct, your app is guaranteed to run the way you expect it to.


I always ask people that say this if they tried using reference counting during the times the borrow checker was too difficult. Rust supports it. There's going to be some performance hit. Most in your situation use GC'd languages, though. So, it seems like Rust with ref counting could still make for easy web development where you get Rust benefits in borrow-checked code but rest is still safe and quick to write.

That's the theory anyway. I haven't gotten any data from people trying that on real-world apps, though. There could be non-obvious problems with it.


The biggest issue, and I fall back on Rc a lot, is that often you end up needing Arc. Especially in async code, where Send is generally desirable. But it's a great way to get around annoyances with shared memory.

I suspect that it might be easy to port most code written in high level languages to Rust if you're willing to use "Rc" or "Arc" liberally. The drawback is Rc does not support cyclic garbage collection (AFAIK), so the resulting code would often have memory leaks.

It does. You just have to use an Rc/Weak Arc/Weak combination.

Weak refs are a way to work around reference counting cycles, but cyclic garbage collection is a more complete solution and it's a core feature of nearly every high level language.

https://www.php.net/manual/en/features.gc.collecting-cycles....

It seems like people who often use Rust's Rc and Arc will long for some way to implement generic cyclic garbage collection. I don't yet see a way (other than unsafe code), but I may be missing something.


Coming from a systems/DSP background, Rust feels at times "higher level" than C/C++ (especially w.r.t. the crates ecosystem, although I suspect a large part of that is its youth and general instability), but mostly akin to writing C-with-classes-style C++ with static analysis baked into your build script.

The "high level" stuff baked into Rust makes it great for "low level" tasks, notably imo:

- Tests (and micro benchmarks, with nightly) alongside code, without dependencies or build system hackery.

- An incredibly powerful macro system, supplanting a lot of the templated code generation I've done in C++ which is a nightmare. Not that proc macros are perfect (yet) but at least they're legible.

- If you've ever tried to do away with dynamic dispatch via templates in place of inheritance, then Rust's generics with trait bounds are an absolute godsend

- A gosh darn dependency solution (now with custom repositories on stable!) makes dependency hell is less hellish


I would describe Rust as, for the most part, a very high-level language, with a strong penchant for zero-cost abstractions. I think many people fall into the trap of considering a language with a static type system as low level. Conversely, Rust's generics, traits, operator-overloading, type inference, substructural typing, and type-directed meta-programming are high-level concepts.

Low-level programming is possible in Rust, as it is in many high-level languages, but it is discouraged. Use of "unsafe" is rightfully met with scepticism.

C++ is also a high level language, but does not enforce use of high-level safety abstractions by default. Web programming in C/C++ is possible, and frameworks exist to do it, but memory safety (security) concerns make it undesirable.


That plus the unfortunate fact that Rust as a language has no specification, so technically speaking, all of Rust is undefined behavior. It's the only thing that holds me back from taking Rust more seriously. I'm enjoying using it on pet projects for now.

You should check out https://news.ycombinator.com/item?id=20105996

And I think it’s a bit more subtle than you’re giving credit for.


Rust has documentation which describes how it's supposed to behave, which is a far cry from everything being undefined behavior. It also has a formal specification of a subset of the language.

It's not like the C/C++ specs are particularly precise. I think people tend to have a mental model of specs as equivalent to formal semantics, which they very much are not.


That wouldn't mean that all of Rust is undefined behavior, it means the compiler is the spec, and the behavior is defined by what the compiler will do. The language having no specification only means that you can't easily determine if what the compiler does is "technically correct", but that's always secondary to the matter of whether the compiler does what you actually want.

What keeps me from Rust is the documentation of the third party libraries. It’s exactly like Java documentation, Here’s 50 classes with functions with no context good luck and have fun! Meanwhile in Python and JS third party libraries have no choice but to provide great documentation front and center. I’m convinced that if there was some kind of tweaks for Rust to be able to tag small inline tests with comments as front page docs, the language usability would shoot through the moon.

Good question. I've been using Rust exclusively for a few months. I came from C#/python. typical GC'd application languages.

With Rust I don't think you have to choose.

Once you "get" the borrow checker and understand the ownership model Rust becomes very productive and feels like a high level language. There's a little noise in the syntax but what you get in return is so worth it. There are quite a bit of high level features to take advantage of that "compile away" with so called zero-cost abstractions.

It's a legit low level language in the sense that you can write a legit OS. No GC, guaranteed memory safety. It's bonkers.

I believe it is blurring the lines of what it means to be high/low level.


Legal | privacy