Hacker News new | past | comments | ask | show | jobs | submit login

Enthusiasm can be a problem.

You don't really need Rust for server-side Web stuff. That's what Go was designed for. Go comes with well-exercised libraries for most of the things people do web server side.

As I've mentioned before, I'm writing a metaverse client in Rust. Now that's something for which Rust is worth the trouble. You need concurrency. A lot of tightly interlocked concurrency. If you want a large high-detail virtual world, you need to keep a half dozen CPUs, a multi-threadable GPU, and the network all quite busy. There's a huge payoff in being able to do all that threading without spending time in a debugger. I've opened a debugger once in the last two years, and that was for a bug in someone else's "unsafe" code.

The price of using Rust is that you hit bleeding edge problems. I just finished writing a basic internationalization package to translate menu items and such. That should be unnecessary at this late date. But it turns out that the basic "internationalization" crate is fundamentally flawed, and even its creator now says so. The crate most commonly used, "fluent", is not suitable for use with the immediate-mode GUI used for games, "egui", because you need lookup memoization for strings retrieved on every frame. A lot of time is wasted on side issues like this.

Many widely used Rust crates are still at version 0.x.x, and not really stable yet. The language and core tools are pretty solid now, but the crates are all volunteer and not well-curated. The graphics systems I'm using, Rend3 and WGPU, are under heavy development, and not yet ready for prime time. I'm in regular contact with those dev groups.

There's not much off the shelf code for metaverses yet. Unity and Unreal Engine don't support metaverses yet, where the content comes from hundreds or thousands of people not working under common management. It's not like picking one of a dozen widely used payment rail systems. So you're going to have to do some serious development from a cold start. Rust is good for that.

For routine web development with short deadlines, Rust may be overkill or unsuitable.




Sometimes I think about how many weeks I’ve wasted debugging my local python environment, managing venvs and various build/package management/testing tools, manually editing my shell’s rc file to approximate a sane dev flow, fixing broken dependencies, re-fixing them whenever I pull changes from one of a dozen repos, etc. I can’t help wonder if Rust would be a net productivity gain solely based on that stuff.

And then, less dramatically but still significant, there’s the runtime errors and all the hand-written JSON (de-)serialization code. It adds up.


I've recently worked on rewriting small-but-not-trivial dynamically typed programs in Rust, and also work on tooling at my company (also written in a dynamically typed language); the sore points you've mentioned are very real and significant.

However, the productivity gains mentioned are an effect of any statically typed language, not just of of Rust, and the problem is that Rust's cognitive overhead offsets them. I definitely would not bring Rust to the table at my company because of that; I've recently had an experience with an engineer who thought it was fun to use, but couldn't write anything with it; I'm sure that with a simpler language, they could have.

I think there are new languages that are a valid middle ground (between Golang and Rust), although they don't have yet enough traction and/or maturity (most importantly, in terms of libraries available) - in other words, they's still hobby languages as of now. I have the suspicion that if a new language will become an established one, it will still take "not few" years, not less than 5/10, unfortunately. I like to use Lambda languages support as an indicator :)


Totally agree. I think Rust advocates can be quite myopic, and tend to frame Rust's advantages relative to C++ or Python/JS in particular. But there are a great many languages which are more productive than Rust, and don't have some of the specific relative drawbacks that C++ or Python do.

I really enjoy programming in Rust, but it's undeniable it makes tradeoffs in terms of productivity for the unique value proposition it presents. The idea that Rust should be used to implement every CRUD webservice, or that Rust -> wasm should be used to implement every web app just seems like irrational exuberance to me.


I'm writing web or web-adjacent code in Python, TypeScript and Rust.

Recently, I ported one of my Python projects to Rust using PyO3 for exactly the reasons you mention. I haven't battle-tested this Rust code yet, so I can't tell you whether this was a good time investment. What I can tell you, though, is that it was much easier than I thought.


Go or even Java. The author talks about how they think Option would reduce errors. Turns out Java has Option. In fact, lots of languages have Option and don't come with all the Rust stuff that you may or may not need. For backend servers, often throwing a GC at it is fine.


> Turns out Java has Option.

While still having nulls everywhere. Rust doesn't have the concept of null at all - Option is the only way to represent the non-existence of something.


Rust has a concept of null, though there are way more nulls in regular Java code than in regular Rust code: https://doc.rust-lang.org/std/ptr/fn.null.html. If the issue is representing non-existence, Kotlin, C# and TypeScript (configured properly) all have nullable types. There's a good chance you'll be more productive with those instead of Rust for regular backends. Of course using Rust still makes sense when you need great performance and/or great safety for a specific service.


> Rust has a concept of null, though there are way more nulls in regular Java code than in regular Rust code: https://doc.rust-lang.org/std/ptr/fn.null.html.

I've used Rust for about 6 years now, and I don't think I've ever used ptr::null(), mainly because I don't really write low-level wrappers around C libraries. I'd argue Rust does not have null as a concept or language feature - ptr::null() is just a convenience function for creating a pointer with the value of zero. The point of not having null is that in most languages null can appear basically in any variable or value, while in Rust null pointers can only exist when writing very low level potentially memory unsafe code.

> If the issue is representing non-existence, Kotlin, C# and TypeScript (configured properly) all have nullable types.

They do indeed have nullable types, but at least in in C# and TypeScript (and probably in Kotlin because of JVM interop) non-nullability is basically a lint with zero runtime guarantees. That is often good enough, but it's still a far cry from an absolute 100% percent guarantee provided by not having nulls even as a concept. Having nulls is a problem you can't fix by adding features - you have to design the language and/or the runtime from scratch without them.

> There's a good chance you'll be more productive with those instead of Rust for regular backends

I'm not arguing against the productivity of these languages or demanding anyone writes anything in Rust. I mostly write TypeScript in my day job, and it is a practical and productive choice for the work we do (web frontends, backends and serverless services). I just want to inform people about the capabilities of Rust and correct misunderstandings.


> non-nullability is basically a lint with zero runtime guarantees

Heh? What else is it in Rust or any other language? Like, the only way I could imagine a null pointer exception leak into C#/JVM-language program that got statically analysed to not contain null is through some Reflection-based unsafe operation - at which point we can also talk about unsafe operations in Rust that just as well can cause “null-pointer exceptions”, except those will be hard memory failings (undefined behavior basically), potentially corrupting the whole execution.


In C# you can explicitly, in the language, basically say "Don't worry this won't be null" and the compiler takes your word for it and lets you do stuff that definitely isn't OK if it's null.

The language has to do this for two reasons. Firstly, this is a retro-fit, so if you don't have this you need to throw away all the old C# code, why not call the new language something else ? Secondly though, and perhaps more important to the C# ethos is you must allow null everywhere to be compatible with the Common Language Runtime. C# has to accept anything the CLR does at any function boundary. This means what can be promised is the lowest common denominator of all CLR languages which exist or are going to exist.

Suppose your C# code checks a string value called username is actually some string, by calling IsNullOrEmpty(). It'd be annoying if after doing that C# just insists username might be null anyway - you just checked! So, that function marks the string reference you called it on as definitely-not-null after having checked. However, you can just make a new function LOLWhatIsSafety() which just always returns 69 and marks the reference as definitely-not-null. In both cases the compiler just takes their work for it.


> In C# you can explicitly, in the language, basically say "Don't worry this won't be null" and the compiler takes your word for it and lets you do stuff that definitely isn't OK if it's null.

You can do this in Rust too. Unsafe Rust is still Rust.


You can, although they're pretty keen on discouraging you from pointing this particular gun at your feet, e.g. ptr.with_addr() can't achieve this on its own because it wants a NonZeroUsize, so first you need to make a NonZeroUsize that's actually zero. But yes, you can write that in unsafe Rust and now your program has Undefined Behaviour.

In contrast all the routes I suggested for C# aren't unsafe, aren't even flagged as "Be super careful here, dragons ahead" because the C# attitude is that every single C# function is responsible for explicitly doing its own null checks if they're needed.


You're right, idiomatic C# will have usually way more nulls than idiomatic Rust.


C#'s null safety is not sound. There are situations where even a fully annotated program without reflection, code generation, unsafe or other tricks will crash of a null pointer exception:

https://docs.microsoft.com/en-us/dotnet/csharp/nullable-refe...


I’m not familiar with C#, so I probably should not have included it. But Kotlin, Scala 3 (with a compiler flag) and even Java with static analysis should be sound, if I’m not mistaken.


Rust has null pointers (which is why it has a function to make a null pointer). But Rust's references, which you use all the time in safe Rust, cannot be "null". As a result Option<&Thing> is the same size as a pointer to Thing, because under the hood the all-zeroes address value is None, other values are Some(address of Thing) but as the programmer you don't need to care how this works, the type system has your back.

You can't do much with a pointer unless you use unsafe Rust. So this provides an easy to see red line for inexperienced developers. "Huh, this is unsafe, I need a grown up".

The affordances for Option<Thing> are - in my biased but experienced opinion after similar time with both languages - superior to those on a nullable type like Thing? in C#. Partly that's historical, Rust has always had Option<Thing> while C# originally had nothing like this, grew nullable value types in a subsequent version and then much more recently got nullable reference types.

The technical mechanism is also much weaker in C#. Suppose a junior dev pastes a Stack Overflow answer in to fix the weird compile error they have. In Rust, if the pasted code is doing something awful with pointer mangling that's unsafe and hopefully your review is like "WTF is this code unsafe?" but in C# maybe there's a null-forgiving operator smuggled in somewhere or some tricks with casting, and now your "Never use null parameters" function is being called with a null parameter. If you complain, Microsoft's C# support will comfort you by explaining that all C# functions are responsible for null checking, even if their signature explicitly says they don't accept null parameters, they need to actually write the checks explicitly, yes this costs at runtime as well as making the code messier with redundant checks everywhere, too bad.

Maybe Kotlin is better? But my guess is that in the JVM ecosystem it's not able to actually deliver better.


Java and especially Scala and Kotlin are much more productive, because they borrowed years of table stakes ergonomic features that Go sacrificed to simplify their compiler. The tradeoff is that we temporarily pay more memory for boxed values and kernel threads.

Rust takes more effort to constrain the solution more tightly, but I would lean toward it for any problem where the JVM is clearly too expensive. I don’t see a lot of design space between them.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: