Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I only have limited experience with Rust (only playing around a bit). But it seems the language forces you to structure the code in a specific way (and you seem to agree). This is good, because it prevents you from making a mess (at some level at least). But what others report (and it matches my limited experience) is that it makes the structure of the code very rigid. So I do not quite see how this does not limit refactoring? What some of you describe in this thread is type-directed refactoring (i.e. you change a type and the compiler tells what you need to change), but is this not limited to relatively basic changes?

In C, you can make partial changes and accept a temporary inconsistency. This gives you a lot of flexibility that I find helpful.



I'll put it like this. Rust causes you to refactor more often and do a full refactoring at once (because the interfaces are so rigid), but it makes it easy to do a full (and correct) refactoring very quickly. Think of it as docs being part of the interface and the compiler forcing you to always update the docs. That's an amazing property


> So I do not quite see how this does not limit refactoring?

Yes it limits refactoring. But all languages provide syntactic and semantic constraints you must operate within. You can't just add line noise to a C program and expect it to compile.

So your complaint isn't that there are limits, it's that there is less of them in C, so it's easier to make changes in C without putting too much thought into it. That is absolutely correct. It's also true that's is far easier to introduce a bug in C code when you refactor than it is in Rust, and that's so because it's harder to write buggy code in Rust that gets past the compiler.

Perhaps an example. Consider:

    inline char foo(uint8_t i, char a[]) { return *(a + 1); }
What does this code do? In C or C++, it's impossible to answer. If i overflows, it's UB. If you go past the end of the array, it's UB. Since it's inlined, there is no way to know if either could happen. If compiler can prove some particular instance is UB, it can do whatever it damned well pleases, without informing the poor programmer. There are lots of worse examples, particularly in C++.

In Rust, it's entirely predictable what happens for any given input, as Rust forbids UB in safe code. But in order to pull that off, Rust forces you to re-write the above function, perhaps into something like this:

    fn foo(i: u8, a: &[u8]) -> u8 { a[(i + 1) as usize] }
or:

    fn foo(i: u8, a: &str) -> char { a.chars().skip((i as usize) + 1).next().unwrap() }
or many other variations depending what you actually need to do. Notice for example you where forced to say whether you're happy with incrementing 255 to 256. If you weren't, you would write it as (i + 1) as usize.

Yes, it's more mental effort. In return, you don't get your arse handed to you on a platter because you recompiled with a newer, smarter version of the compiler that noticed you violated some language rule only a language lawyer would know, and took advantage of it.




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

Search: