Hi all,

I started learning rust a few months ago on my free time. I went through the most difficult already like borrow checker and I used the Learning Rust book from Jim Blandy as reference especially for its first chapters.

This is not my first time learning a language I already have experience with Python, Go, JS, C, Lua … but with Rust it feels different.

Everytime I learned a new lang there was always a milestone I crossed that made me feel comfortable using the language, that milestone was always some side project or program I needed anyway.

I am trying to do the same with Rust but the slowness of learning and looking up the docs coupled with the verbosity of the language is not very motivating. Don’t get me wrong, I really want to use Rust and learn it as it looks very elegant and clean, I already learned a lot more about lower level details of programming. The documentation is probably the most elaborate one I ever used for a programming language.

To keep me going I am practicing Rustlings while a procrastinate to work on the side project I chose as first project.

I am just curious how others passed that milestone with Rust.

  • orclev@lemmyrs.org
    link
    fedilink
    English
    arrow-up
    3
    ·
    1 year ago

    Pretty much anything is going to be a softer introduction than Haskell, it’s like the black diamond level course of strong typing and functional programming. That said learning it fundamentally shifted the way I think about programming in what I consider to be a good way.

    With Haskell, when you finally manage to get your code to compile without error, it will usually work and be bug free. The reason for that is that its type system and the constraints of its functional language design have forced you to really sit down and think about exactly how your code is going to react to every possible situation. Rust is similar but provides a lot more lazy options for you. For instance if you really don’t care if your code crashes at some particular point you can just slap .unwrap() on something and call it a day. That’s basically telling the compiler “I either don’t expect this to error, or if it does error I just don’t care, kill the program and call it a day”. This is in contrast to Haskell that would have forced you to explicitly handle the various error conditions and explicitly opt into killing your program at that point. In either case though the fact that something has returned a Result wrapped value (or the Haskell equivalent of Either) has explicitly forced you to think about the fact that whatever returned that value might have produced an error instead and what you want to do in that situation.

    Having to actually think about errors and how to react to them is a massive win for writing correct and bug free programs. Other languages let you just assume that everything is going to work, but there are all these places that errors can occur but often don’t so you get in the habit of thinking as if errors can’t occur there, then when they do it’s always a shock. C is particularly bad about this because there’s all kind of places where C functions return garbage results and you only know they’re garbage if you check the global error variable, which you totally remembered to do right?

    I guess the point I’m trying to make in a roundabout fashion is that Rust somewhat, and Haskell definitely, force you to spend a lot longer writing your code in the first place because you need to put some thought into how the code will react to various situations in an imperfect world where various things just don’t work like they should, but the end result is code that lacks surprises. It’s always going to behave like you expected it would (assuming your understanding of whatever algorithm or business rule you’re implementing is correct) which ultimately saves a ton of time debugging. Having a compiler error that points you at a particular line of offending code with a (hopefully) clear explanation of why that particular line is problematic is so much simpler to deal with than a cryptic error message at runtime that could be coming from a barely even related part of the code due to a whole series of assumptions having failed in the face of one unhandled error state.