5 ms·
I tried to learn Rust 4 times. I'm sorry, but I can't get past the syntax. Just _look_ at all these short keywords and special symbols. It's legitimately hard
by optymizer 6y ago
I tried to learn Rust 4 times. I'm sorry, but I can't get past the syntax.
Just _look_ at all these short keywords and special symbols. It's legitimately hard to read without focusing on each character.
#[bla(foo)]
fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {
println!("x is {} and y is {}", x, y);
}
impl<'a> Default for Borrowed<'a> {
fn default() -> Self {
Self {
x: &10,
}
}
}
This old fart thinks Rust is the new Perl.
- coldpie 6y agoWell, that is a particularly complicated example. I actually shipped my first Rust code just a couple months ago and it rarely used lifetimes. There is definitely a learning curve, but that true of any language. Rust's insistence on safety makes it less forgiving than other languages, but I think that's a plus. We have enough unsafe languages already, and we're paying the price for it now. Here's a representative example of the code I wrote. This bit is outputting stuff to a file in some binary format: https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/fossilize.rs#L211 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med... E: If you want to take another stab, the way I learned Rust was the book: https://doc.rust-lang.org/book/ https://doc.rust-lang.org/book/ Actually type out every code example, it will help your fingers learn the "feel" of the language, and give you an opportunity to break things on purpose to test your understanding. Learning something new is always a challenge, but I really do like Rust and think it's worth the trouble.
- optymizer 6y agoThanks for providing a real world example of code that looks fine in Rust. If you're not using lifetimes, do you still get all the safety guarantees?
- coldpie 6y agoYes, definitely. You only need explicit lifetimes for when it's impossible for the borrow checker to figure out the lifetimes for itself. For example if one struct references another, the borrow checker can't know which struct should outlive the other. The vast majority of the time, the borrow checker can figure it out automatically without your help. It's discussed here[1] but note that it's Chapter 10 of the book, so it's probably not the best place to start reading if you're new to Rust :) [1] https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html E: There are only three instances of using explicit lifetimes in the entirety of the project I linked, if you want to see some real-world examples of it. In all of these, it is used to indicate that the struct being declared references another struct which must outlive that struct. That way we don't end up with a dangling reference if the referenced struct failed to outlive this struct. https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/audioconv.rs#L406 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med... https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/videoconv.rs#L133 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med... https://github.com/ValveSoftware/Proton/blob/proton_5.13/media-converter/src/videoconv.rs#L433 https://github.com/ValveSoftware/Proton/blob/proton_5.13/med...
- lalaithion 6y agoYou're always using lifetimes, but you rarely have to write them out. Writing out lifetimes is only needed when you have a particularly complicated function or data structure; usually the compiler can just compute what the right lifetime should be from the control flow and type of the function.
- secondcoming 6y agoStop salting the syntactic sugar!
- leetcrew 6y agoaside from the lifetime annotations, how is that worse than C to an unfamiliar reader? the format specifiers for printf and friends are way worse than anything in your rust example.
- optymizer 6y agokeeping in mind that this is about syntax, here's what I think is actually worse (but I understand that everyone is different so if you like these, it doesn't really matter what I think): #[] - why the [] if # already makes that line different from the usual code? seems superfluous 'a - is that thing next to 'a' a smudge on my display? Did I forget a quote? better wipe the display with my finger '&a - "mut" and "ref" but ' ? foo! - yelling out function calls. "print!" "exit!" "macro!". Angry Codes! foo? - when you're done yelling, make sure to ask existential questions of the return result. This one I have the least problems with since it actually makes me question the return value ("hm, something's weird here, it could be null, pay attention"), but when coupled with the yelling, just makes the whole thing look dramatic. "do_it_now!(); did_we()?" fn - by itself not a huge deal, but the list of truncated words that are used frequently is "impl", "mut" and "pub". I save some characters (am I really in such a rush?) at the cost of reading this broken English "f-n impl moot pahb". At least C doesn't have that. Pascal had "interface" "implementation", "begin", "end", etc. Java has "public", "interface", "extends", "class". Default for Borrowed - suddenly English! No time to type 'function' or 'mutable' but "Default for Borrowed" is a-ok? underscores all over the place in the standard library. Even C doesn't have that many, mostly in the _r variants that were added. unwrap() - what does that word have to do with errors? (I know what it does) It wouldn't be my first choice. I have a whole list of awesome stuff, meh-stuff and wtf-stuff I noted down about Rust while trying to learn it (on multiple occasions), and there are a lot of excellent things about Rust, but the aesthetics of the language are important, otherwise we'd all have no issues coding in Brainf*ck. Yes it's possible to go nuts with syntax, but this just feels like the "programmer art" of language syntax. I think it's usable (clearly), it's just not elegant to me.
- leetcrew 6y ago> #[] - why the [] if # already makes that line different from the usual code? seems superfluous I don't even know what #[bla(foo)] does, or why all that punctuation is needed. maybe nesting is allowed? > 'a - is that thing next to 'a' a smudge on my display? Did I forget a quote? better wipe the display with my finger this is a lifetime annotation, which is a genuinely noisy bit of syntax. > foo! - yelling out function calls. "print!" "exit!" "macro!". Angry Codes! I guess they really want to make sure you know when a macro is being used. probably a result of ptsd from debugging c and c++ code :) > fn - by itself not a huge deal, but the list of truncated words that are used frequently is "impl", "mut" and "pub". I save some characters (am I really in such a rush?) at the cost of reading this broken English "f-n impl moot pahb". At least C doesn't have that. the c keywords aren't too bad, but the standard library is full of this kind of thing. stdio.h and string.h immediately come to mind. I'm not so much defending rust as I am pointing out that c's syntax isn't that great to begin with. I've been writing c and c++ code every day for several years now, so it's usually pretty easy for me to skim and understand what is going on. but if I try and place myself in the shoes of a newcomer, I don't think the syntax is much better than rust. remember the first time you tried to parse the type of a nontrivial function pointer?
- icedchai 6y agoI have the same problem. I found Rust too syntactically noisy.
- StillBored 6y agoYah, my take on rust is that its needlessly verbose in places where it doesn't make sense (structures anyone?) and to terse in places where it needs more verbosity and the rules frequency don't make sense (implicit types). Much of it appears to just have been handicaps in the original compiler implementation. At this point someone should step away from the compiler implementation look at how people are working around the language and do a 2.0/"use strict" type thing where they redefine much of the language. Then like what happens with new C++ revisions let the compilers catch up.
- dkarl 6y agoI think it's a subconscious habit of how your eyes traverse the code. Your mind has been trained to skip over a lot of those symbols and get the meaning from the surrounding code, and in the near term, it costs extra work to suppress that habit and actually see the symbols. Over the long term, I don't think symbols are harder to read than keywords. C itself provides some evidence for that: imagine reading C code if experience with another language had conditioned you to look past * and &. That would be terribly confusing, but for an experienced C programmer, those symbols leap out of the code at you because you know that they carry a lot of meaning.
- turndown 6y agoI only know Rust well enough to read simple programs, and I had no problem reading your example.
- arcticbull 6y agoYou don't need to specify the lifetime annotations on print_refs because the references aren't returned and are unambiguously just the lifetime of the function. The compiler will fill those in for you -- even if the lifetimes of x and y are different, just so long as x and y live at least as long as the function. fn print_refs(x: &i32, y: &i32) { println!("x is {} and y is {}", x, y); } In general you only need to specify lifetime parameters when there's an ambiguous situation. For instance, the following builds and runs just fine. fn make_substring_of(input: &str) -> &str { &input[1 .. ] } I'll be the first to admit it takes a while to ramp up into Rust. Part of that is learning to let go and trust the compiler. Unlike many other languages, it won't hurt you haha. It's on your side. Sometimes you need to you know, give it a little more info so it can do it's job. The Rust team has made huge strides in improving writability of the language, especially with non-lexical lifetimes. Soon, `fn` and `impl` and `Vec` fade into the background, like `char` and `short` and `long`.
- dnautics 6y agoyou might like zig.