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.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/med...
E: If you want to take another stab, the way I learned Rust was the 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.
[1] 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/med...
https://github.com/ValveSoftware/Proton/blob/proton_5.13/med...
https://github.com/ValveSoftware/Proton/blob/proton_5.13/med...
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`.
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.
#[] - 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.
int and char aren't exactly words. And let's not forget that a type like "double" makes no sense whatsoever by itself. (It's two of something, but two of what? Oh, it's "double-precision" floating point! How could I miss that?)
Now, let's look at C's standard library:
strcmp, strpbrk, isalnum, ispunct, setjmp, SIGSEGV, SIGFPE (that's the divide-by-zero exception, isn't it obvious?), SIGABRT
Sure seems like C has its own massive issue with "we can't let a name be long"
> underscores all over the place in the standard library. Even C doesn't have that many, mostly in the _r variants that were added.
va_arg, FE_DFL_ENV, int32_t, etc. Continue on into most C libraries, and underscores are pretty common because C has no other namespacing mechanism.
Syntax is pretty strange in any language if you're not used to it. If you're comfortable with C, C's syntax and spelling quirks don't stand out to you.
I personally have higher expectations of a language designed in the 2000s by people standing on the shoulders of 40 years of computer science and language research.
Here's a contrived analogy:
Imagine if you bought the newest Tesla truck meant to replace old Ford model trucks and you had to vigorously shake the steering wheel in order to lower the driver's window.
You're saying: "Ford trucks have always used a hand crank and that feels strange too if you're not used to it!"
I'm saying: "Why did they choose to make it equally strange in the first place?"
Ahh yes, I believe that came about due to the great "Vowel Bowl" of the 1970s. There was a serious shortage of vowels.
Since the first edition of ANSI/ISO C was trying to codify the already-existing common practices for maximum portability, it reflects those existing limits (5.2.4.1 "Translation limits"):
"The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits:
...
31 significant initial characters in an internal identifier or a macro name
6 significant initial characters in an external identifier"
If you look at many abbreviated function names from the C stdlib, they are specifically 6 characters long - strcpy etc. I wouldn't be surprised if the 6-char external identifier limit goes all the way back to the first K&R C compilers.
> #[] - why the [] if # already makes that line different from the usual code? seems superfluous
# does not "make that line different from the usual code." The whole #[] construct is it, it has nothing to do with lines. You could put "#[foo] #[bar]" on one line if you wanted, you could write "#[foo] fn lol()" if you wanted...
> foo! - yelling out function calls. "print!" "exit!" "macro!". Angry Codes!
This helps both humans and computers parse; macro invocations don't have to follow regular Rust syntax, and the ! helps indicate that that's true.
> Default for Borrowed -
This is not language syntax, this is the name of two types. You can name your types however you'd like.
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?
People proposing every other language that tried to replace C thought the same. Only time will tell, of course, but I wouldn't bet on it. Nowadays C++ is seen by many as a "garbage pile", the same can happen to rust.
Did you mean API? The C++ ABI situation is famously unstable.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p186...
"there is a non-trivial amount of performance that we cannot recoup because of ABI concerns. We cannot remove runtime overhead involved in passing unique_ptr by value, nor can we change std::hash or class layout for unordered_map , without forcing a recompile everywhere etc. etc."
I thought passing template instantiations over an ABI boundary was generally discouraged and thought to be asking for trouble. I guess this isn't really at odds with what the paper is saying though - it could still be that a lot of people are doing so.
edit Thinking about Hyrum's Law, [0] mentioned in the article, makes me think perhaps there was an upside to Java firmly refusing to support any kind of ahead-of-time compilation for so long. It fully closed the door on any funny business distributing Java packages as brittle precompiled native-code blobs, ensuring the bytecode format remained the way that Java packages were distributed, presumably avoiding some fraction of the issues C++ now faces.
Of course, Java still has backward-compatibility obligations, but unlike in C++ they align pretty well with API compatibility, if I understand things correctly.
is a couple ABI breaks for std::string between C++98 and C++20 that unstable ? You can write code that uses std::string today and links against a .so built a long time ago (modulo compiler bugs of course, thus the various versions here: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Optio...). GCC & libstdc++ go to great lengths to preserve ABI compatibility.
C++ was seen as a garbage pile from its inception by a large number of people.
A significant number of people kept using C because the only alternative was C++ and that wasn't acceptable.
I am sure it has its place but I think it's just too ugly to be attractive. There is something pleasing about writing C, Python or even Javascript which you will never get with Rust. It will never be a language a lot of people enjoy writing imo.