Live data from Hacker News

My Struggles with Rust

compileandrun.com

1–10 of 329 posts

Re: My Struggles with Rust

#2
These struggles are real. I don't see a way around them other than just learning them (and then they go away, because you know what code won't work, and don't fight it).

It's probably because Rust looks and operates mostly like a high-level language, but still satisfies low-level constraints.

e.g. the confusing difference between `&str` and `String` is equivalent of C's `const char * str = ""` vs `char * String = malloc()`.

In C if you had a code that does:

     char *str = foo();
     free(str);
you'd know that in `foo()` you can't return `"error"`, since an attempt to free it would crash the program. And the other way, if the caller did not free it, you'd know you can't have a dynamic string, because it would be leaked. In Rust you don't see the `free()`, so the distinction between non-freed `&str` and freed `String` may seem arbitrary.

Re: My Struggles with Rust

#3
post #2

These struggles are real. I don't see a way around them other than just learning them (and then they go away, because you know what code won't work, and don't fight it). It's probably because Rust looks and operates mostly like a high-level language, but still satisfies low-level constraints. e.g. the confusing difference between `&str` and `String` is equivalent of C's `const char * str = ""` vs `char * String = mal…

These struggles are indeed real, but at least as far as verbose error handling goes, remember that Rust is forcing you to handle a lot of things that are silently ignored in Python. Truly equivalent Python code would include a bunch of exception handling and checks for nil.

Re: My Struggles with Rust

#4
My main gripe with Rust so far has been the unnecessary profusion of Result types, making it hard to process and forward errors.

Case in point: the example in the article from the rust documentation that converts errors to strings just to forward them: https://doc.rust-lang.org/book/error-handling.html#the-limit...

In practice, I find a type like Google's util::StatusOr (https://github.com/google/lmctfy/blob/master/util/task/statu...) a lot easier to use (I've written >100kloc c++ using it). This uses a standardized set of error codes and a freeform string to indicate errors. I've yet to encounter a case where these ~15 codes were insufficient: https://github.com/google/lmctfy/blob/master/util/task/codes...

Re: My Struggles with Rust

#5
Being able to port a 20 line Python script to a 20 line Rust is the holy grail. Surely Rust has the ambition to one day achieve that, but it is by no means the main priority nor the original design goal of the language.

Justin criticizes the file_double function, it being complex with nested maps and conditionals. All of this complexity is also in the Python code, just hidden away in abstractions, the library and the virtual machine. Rust, right now, is still very explicit and revealing of inherent complexities. This code is exactly why you should use Python and not Rust for this kind of little script. One day the Rust developers hope Rust will be comfortable enough for you to consider using Rust in this situation, but it won't be soon.

The point gets softened a little by the remark that it probably would not be a picnic in C either, but I don't think even that is true. C still allows you to be very expressive, it would not encourage using those maps or even half of those conditionals. Rust is just that more explicit about complexity.

That said I honestly believe Rust is the best thing that has happened to programming languages in general in 20 years. Rust is rocking the socks off all the non-web, non-sysadmin fields, soon its community will make good implementations of almost every hard problem in software and Rust will be absolutely everywhere.

Re: My Struggles with Rust

#6
post #4

My main gripe with Rust so far has been the unnecessary profusion of Result types, making it hard to process and forward errors. Case in point: the example in the article from the rust documentation that converts errors to strings just to forward them: https://doc.rust-lang.org/book/error-handling.html#the-limit... In practice, I find a type like Google's util::StatusOr ( https://github.com/google/lmctfy/blob/master/…

With the addition of `?` operator I think it's no longer the problem. It keeps error handling explicit, but the syntax is small enough that it doesn't make code noisy or tedious to write.

Note that you can also make your functions return `Box` which works like a base class for all common errors, so you don't have to worry about converting error types.

Re: My Struggles with Rust

#7
The big question is would the Python script crash or handle the error when obvious problems like not valid JSON or file not found happen?

My experience with Swift vs Objective-C is that clean Swift is crash free but more verbose when all other things are equal.

If you don't need that level of security because it's just a small script Python was the right choice.

Re: My Struggles with Rust

#8
post #2

These struggles are real. I don't see a way around them other than just learning them (and then they go away, because you know what code won't work, and don't fight it). It's probably because Rust looks and operates mostly like a high-level language, but still satisfies low-level constraints. e.g. the confusing difference between `&str` and `String` is equivalent of C's `const char * str = ""` vs `char * String = mal…

> It's probably because Rust looks and operates mostly like a high-level language, but still satisfies low-level constraints.

In an ideal language, you could decide to ignore low-level constraints and your code would work just fine, although perhaps less efficiently.

Re: My Struggles with Rust

#9
post #5

Being able to port a 20 line Python script to a 20 line Rust is the holy grail. Surely Rust has the ambition to one day achieve that, but it is by no means the main priority nor the original design goal of the language. Justin criticizes the file_double function, it being complex with nested maps and conditionals. All of this complexity is also in the Python code, just hidden away in abstractions, the library and the…

The file_double code was, IMO, quoted completely out of context. If you go read the error handling section, that code is used as a motivation to the next section, where you get gradually introduced to more economical error handling.

The error handling chapter is... Really big. Because it tries to explain everything from first principles. But it does include explanation and examples for using easy error handling as well, whose syntactic noise and level of boiler plate come quite close to Python.

Re: My Struggles with Rust

#10
The `error-chain` crate [1] exists to get rid of precisely the error handling boilerplate the author has encountered. That's not ideal, though, as I believe that a place for such functionality is in the core language, not a separate library, but it gets the job done. As for the `let mut file` bit, that makes sense to me: a file in the standard library is an abstraction over a file descriptor in the operating system, and the descriptor has a file pointer which must be advanced when you read from it. I don't consider it internal state; the read operation will return new data every time, so it's not a pure function. It follows that in order to behave that way, it has to depend on some pretty explicit state.

As the other comment said, Rust needs to make some trade-offs, because you simply can't have an expressive and easy-to-use language that runs so close to the metal and is aimed at being C++-level fast. As such, Rust will never be as easy to write as Python, and for scripts like the author mentioned, I'd say that Python is a much better choice than Rust.

Rust is, by design, a systems programming language and it does have complexities and gotchas that arise from the need to have a lot of control of what actually happens at the machine code level. If we had a Sufficiently Smart Compiler(tm), of course, you wouldn't have to worry yourself about those low-level details and just write what your program needs to do and nothing more. However, in the absence of such an ideal, we must accept that a high-level abstraction must always leak in some way in order to let us control its operation more closely to get the performance we need. In my opinion, it's much better that necessary abstraction leakage is made a deliberate part of the API/language and carefully designed to minimize programmer error, and Rust, I think, does a good job of doing exactly that.

That's not to say that the language cannot be made more ergonomic. For one, I think that rules for lifetime elision are a bit too conservative and that the compiler can be made smart enough to deduce more than it currently does. I'm also excited about the ergonomics initiative, and I hope that the core team will deliver on their promises. In general, as someone who's written more lines in C/C++ in my life than any other language, I'm very excited about the language as a whole, as I think it provides the missing link between those languages that are expressive, high-level, and reasonably safe but slow, and those that are fast, low-level, a bit terse, and allow one to shoot oneself in the foot easily.

[1]: https://crates.io/crates/error-chain

Post reply on HN