logoalt Hacker News

its-kostyayesterday at 11:34 PM9 repliesview on HN

I write production Rust code that becomes critical infra for our customers. I got tired of nil checks in Go and became a squeaky wheel in incident retros, where I finally got the chance to rewrite parts of our system in Rust during a refactor.

I admit the skill issue on my part, but I genuinely struggled to follow the concepts in this article. Working alongside peers who push Rust's bleeding edge, I dread reviewing their code and especially inheriting "legacy" implementations. It's like having a conversation with someone who expresses simple thoughts with ornate vocabulary. Reasoning about code written this way makes me experience profound fatigue and possess an overwhelming desire to return to my domicile; Or simply put, I get tired and want to go home.

Rust's safety guardrails are valuable until the language becomes so complex that reading and reasoning about _business_ logic gets harder, not easier. It reminds me of the kid in "A Christmas Story" bundled so heavily in winter gear he cant put his arms down[0]. At some point, over-engineered safety becomes its own kind of risk even though it is technically safer in some regards. Sometimes you need to just implement a dang state machine and stop throwing complexity at poorly thought-through solutions. End old-man rant.

[0]: https://youtu.be/PKxsOlzuH0k?si=-88dxtyegTxIvOYI


Replies

sam0x17today at 5:25 AM

I feel you, but hear me out. OP is right. I've wanted pretty much everything he's talking about here for years, I just never thought of all of this in as quite a formal way as he has. We need the ability to say "this piece of code can't panic". It's super important in the domains I work in. We also need the ability to say "this piece of code can't be non-deterministic". It's also super important in the domains I work in. Having language level support for something like this where I add an extra word to my function def and the compiler guarantees the above would be groundbreaking

nemothekidtoday at 2:48 AM

I've been on both sides of the fence here - I've bounced between two camps:

1. Go with a better type system. A compiled language, that has sum types, no-nil, and generics.

2. A widely used, production, systems language that implements PL-theory up until the year ~2000. (Effects, as described in this article, was a research topic in 1999).

I started with (1), but as I started to get more and more exposed to (2), you start looking back on times when you fought with the type system and how some of these PL-nerds have a point. I think my first foray into Higher-Kinded Types was trying to rewrite a dynamic python dispatch system into Rust while keeping types at compile time.

The problem is, many of these PL-nerd concepts are rare and kind of hard to grok at first, and I can easily see them scaring people off from the language. However I think once you understand how they work, and the PL-nerds dumb down the language, I think most people will come around to them. Concepts like "sum types" and "monads", are IMO easy to understand concepts with dumb names, and even more complex standard definitions.

show 1 reply
ajxstoday at 9:10 AM

At the risk of sounding like a language zealot, have you ever looked at Ada? It was explicitly designed to be very readable, and for use in safety-critical systems. Ada isn't perfect in all the ways Rust isn't, and it might not be the right choice for your system, but if you're writing systems software it's worth a look. If you're writing a web backend on the other hand, it's not worth a look at all.

tormehtoday at 10:00 AM

Nothing can really save you from architecture astronauts, except possibly Go, but I hear there are people templating Go with preprocessors, so who knows. This is a human problem. On the other hand I hear you. The moment Rust gets proper async traits an entire world of hexagonal pain will open up for the victims of the astronauts. So it will get even worse, basically. I think if we could solve the problem of bored smart people sabotaging projects it'd be amazing.

olalondetoday at 6:21 AM

Can we get a version of Rust that swaps lifetimes and ownership for a GC and a JS-style event loop? I love the DX of the language, but I don't always need to squeeze out every microsecond of performance at the cost of fighting the borrow checker.

show 3 replies
QuaternionsBhoptoday at 1:21 AM

> Reasoning about code written this way makes me experience profound fatigue and possess an overwhelming desire to return to my domicile;

I didn't understand that you were making fun of verbosity until the word 'domicile'. I must be one of those insufferable people who expresses simple thoughts with ornate vocabulary...

The article was comprehensible to me, and the additional function colorings sound like exciting constraints I can impose to prevent my future self from making mistakes rather than heavy winter gear. I guess I'm closer to the target audience?

babytoday at 2:14 AM

I really think that golang makes it easy to read code, rust makes it easy to write code. If Golang had sum types it would be a much nicer language to write complex applications with

show 2 replies
rob74today at 6:30 AM

I experienced the same kind of fatigue when I read "there are three directions of development which I find particularly interesting: [three things I never heard about nor particularly want to get familiar with]" in the article.

And later, when I read "Because though we’re not doing too bad, we’re no Ada/SPARK yet" I couldn't help thinking that there must be a reason why those languages never became mainstream, and if Rust gets more of these exciting esoteric features, it's probably headed the same way...

gignicotoday at 8:27 AM

I think the misunderstanding here is that the article was not intended to users but to other language designers.

As a user, using a feature such as pattern types will be natural if you know the rest of the language.

Do you have a function that accepts an enum `MyEnum` but has an `unreachable!()` for some variant that you know is impossible to have at that point?

Then you can accept a `MyEnum is MyEnum::Variant | MyEnum::OtherVariant` instead of `MyEnum` to tell which are the accepted variants, and the pattern match will not require that `unreachable!()` anymore.

The fact someone does not know this is called "refinement types" does not limit their ability to use the feature effectively.