Live data from Hacker News

Migrating from Go to Rust

corrode.dev

541–544 of 544 posts

Re: Migrating from Go to Rust

#541

Earlier quoted context omitted.

How it reads to me: "This is easy. No problem! There's reams of pages written about it, because it's easy, which is always why whole treatises get written about stuff. I can't think of the best to recommend right now, not because the topic is nuanced and there's no best one and you probably have to read many different things to determine whether to e.g. reinvent pointers as integer indexes into arrays, but don't take…

I was not asserting it was easy nor trying to attack you. Merely recommending you find reading material because your understanding is lacking. You’ll probably find it scratching an itch when you realize how nicely it all composes together. Though I have little hope for that after your little drive-by at memory safety further showcasing you’re way out of your depth

I feel pretty comfortable with my level of conversance with these issues, but if you think "you're way out of your depth" is persuading readers of this thread, have at it; you have my permission to establish to those readers that that's the level you're arguing at.

Re: Migrating from Go to Rust

#542
post #435

Earlier quoted context omitted.

There's a number of things about rust that help compared to other statically typed languages. 1. the compiler gives very high quality error messages. It helps humans, and also helps LLMs 2. Rust reduces memory management to local reasoning (via the borrow checker). This means that it performs well even as context grows, because checks in one function/module are well-encapsulated to that function/module. 3. Rust can m…

> This is both good practice, and helps out LLMs quite a bit. Don’t get me wrong, I like this aspect of Rust, but I can’t make heads or tails as to whether it helps or if they just have to iterate more to figure out how to make something work. LLMs already do pretty well with a comment “this value can’t be zero” in my experience, so I’m unsure how much value the static typing provides. Maybe it lets you get by with a…

LLMs do significantly better when they get reliable feedback on their actions (try to create any non-trivial project in some language without letting the LLM use a compiler. Similarly, talking with a "chat LLM" will produce worse code than an "agentic LLM").

Anyway, making such a (breaking) change in rust immediately tells you all of the callsites that break. You have to chase it through, but that's mechanical/low context work. More formally, you can parallelize across files with sub-agents to not pollute your main agents context window. So it really should be a "zero context window" cost.

Whether or not strict typing is strictly better is really a correctness/velocity tradeoff, the same as it always has been. For most projects something in the middle is right.

As for owned vs borrowed and things propagating quite a bit, sometimes it happens. It's often avoidable with a couple of tricks

1. always default to borrowed unless you have a good reason to otherwise

2. make your function signatures more permissive so they can support either way. This can be done by modifying f(x: T) (or f(x: &T)) to f>(x: U). The later can be equivalently written as f(x: impl AsRef).

When you say "change a field from owned to borrowed", I'd generally suggest not doing that. It's generally easier to start with some owned type MyType. You can then have function signatures take &MyType as input. This borrows all the fields, and is often good enough for most functions.

If you have a more esoteric function (that needs a combination of borrowed and owned inputs), it's typically easier to define a struct for that function. The steps are

1. Define a FunctionInputsRef

2. write `impl From for FunctionInputsRef`, then

3. update your function to take as input FunctionInputsRef rather than `&MyStruct`, and

4. update callers with `input -> input.into()`.

It has the benefit of less churn, as you're maintaining the old def (which might be useful elsewhere), and only updating the callers in a fairly trivial way. `FunctionInputsRef` can also be defined local to the function, so it is modularized better. If you later have other functions with other requirements, it's a relatively easy pattern to duplicate as well.

Re: Migrating from Go to Rust

#543

Earlier quoted context omitted.

I was trying to be sympathetic and acknowledge virtualenv's potential flaws, actually, even though I haven't personally encountered them, but I guess that was a waste of time.

Which part of this is sympathetic? > This is unrealistic. You seem to have moved to Go as an alternative, but I know because I've seen the complaints that Go doesn't satisfy that standard either. It's a dig - you completely ignore the valid complaints about Python to instead focus on what you think will provoke me. The problem (for you) was, from the very start, I bought up the pain points with Go.

> Still, I'm not saying the problems aren't real, ...

> I'm going to blame that on Amazon frankly. That's definitely bizarre.

I'll grant I lost track of the context that you were trying to raise the possibility of some grand encompassing solution to all programming language package management. All I wanted was to reinforce the idea that virtualenv is Often Just Fine in practice, at least if used in sensible ways.

Re: Migrating from Go to Rust

#544

Earlier quoted context omitted.

> track down a situation where you see in your prod logs that you are encountering a lot of "validation error: string is too long" but you can't tell where it is coming from. Capturing a stack trace is a hefty operation: making it happen on _every_ error creation, which would include creating an error in response to another error (like causing ) could easily grind a production server to a halt. Especially if there's…

I feel like we are talking past each other, because you ignored the whole part about "it is already tied to an env var, and it would be still tied to an env var" that you would only enable on demand, so who cares if it's a hefty operation? Also what about other languages that capture stacktraces all the time with exceptions, or scripting languages with type errors, where you can't even turn it off? Rust is somehow di…

Rust errors are not exceptions. Catching exceptions is unbelievably expensive in all languages that support them, compared to handling a Rust error value.

Some languages have exceptions as the only error handling mechanism (C#, Java, scripting languages), and it sounds like that's what you're used to. But this is also broadly agreed to be a severely limiting factor of those languages, resulting from being designed at a time when we didn't know better.

If you want to go fast (and Rust does), you cannot be catching exceptions in the hot path, and you certainly can't be throwing exceptions that carry stack traces, because walking the stack to build up the stack trace is many orders of magnitude slower than returning an error value.

Rust's error handling modes are designed with the benefit of hindsight from all those other languages from the last few decades, and reflects the fact that errors broadly fall in two categories: validation failures and programmer errors. The former should be a cheap error code that can be handled, the latter should terminate the program/thread/task and give you enough information to diagnose the problem.

Post reply on HN