“fn” was just one example. There’s also other abbreviations like “pub”, “impl”, “extern”, “mut”, “ref”, “bool”, “u64” And it’s true that some of these keywords are only relevant in Rust, however other langues have their own specific keywords, and they tend to be longer. In languages like Java (which is the worst example I can think of), you see things like “private static boolean” as function definition. In c++, you have to type “unsigned long” or even “unsigned long long” to represent “u64” (depending on data model).
I really don’t agree with saving keypresses being a useful metric, since auto-completion is a thing and code is read significantly more often than it is written. I am also a staunch opponent of abbreviations being used for variable names.
But I will say that I don’t mind abbreviations in keywords, since well, you need to learn the meaning either way.
And yeah, I’ve come to somewhat like them being used for keywords, since it reduces visual noise where it really isn’t useful, and it distinguishes keywords from actual code.
Ultimately, keywords are just syntax where letters were used instead of a symbol. You do read them like a symbol, so if they don’t look like a real word, that seems to work quite well for my brain.
C++ is even worse, due to templates and the so-called most vexing parse. Initializing with {} mitigated the latter somewhat, but came with its own set of woes
To be honest, I think, they both have their place. In Rust, you typically wouldn’t return just a bool, but rather the element that you removed, so like this:
I believe that it is useful in a few places. cppreference.com mentions templates as one case:
Trailing return type, useful if the return type depends on argument names, such as template<classT, classU> autoadd(Tt, Uu) -> decltype(t + u); or is complicated, such as in auto fpif(int)->int(*)(int)
The syntax also matches that of lambdas, though I’m not sure that adding another way of specifying regular functions actually makes the language more consistent, since most code still uses the old style.
Additionally, the scope of the return type matches the function meaning that you can do
Rust:
fn getofmylawn(lawn: Lawn) -> bool { lawn.remove() }C:
bool getofmylawn(Lawn lawn) { return lawn.remove(); }With Rust you safe 1 char, and gain needing to skip a whole line to see what type something is.
“fn” was just one example. There’s also other abbreviations like “pub”, “impl”, “extern”, “mut”, “ref”, “bool”, “u64” And it’s true that some of these keywords are only relevant in Rust, however other langues have their own specific keywords, and they tend to be longer. In languages like Java (which is the worst example I can think of), you see things like “private static boolean” as function definition. In c++, you have to type “unsigned long” or even “unsigned long long” to represent “u64” (depending on data model).
To be fair, in C/C++ you can include
stdint.hwhich defines type aliases such asuint64_t.I really don’t agree with saving keypresses being a useful metric, since auto-completion is a thing and code is read significantly more often than it is written. I am also a staunch opponent of abbreviations being used for variable names.
But I will say that I don’t mind abbreviations in keywords, since well, you need to learn the meaning either way.
And yeah, I’ve come to somewhat like them being used for keywords, since it reduces visual noise where it really isn’t useful, and it distinguishes keywords from actual code.
Ultimately, keywords are just syntax where letters were used instead of a symbol. You do read them like a symbol, so if they don’t look like a real word, that seems to work quite well for my brain.
Honestly, the Rust way of doing things feels much more natural to me.
You can read it as
getoffmylawn,Lawnargument namedlawn,boolWhereas the C function is read as
bool? Could be a variable, could be a function, could be a forward declaration of a function,getoffmylawn,(, so all options are still on the table,Lawnargument namedlawn, that returns abooltypes in C are pretty weird
int *acan be read as*ais a intais a pointer tointint *a, bis read as*aandbareintais a pointer tointandbis aintbool getofmylawn(Lawn lawn)getoffmylawn(Lawn lawn)is aboolgetoffmylawnis a function that takes aLawnand returns aboolAnd then you have function pointers
bool (*foo(int a))(float b)(*foo(int a))(float b)is abool*foo(int a)is a function fromfloattoboolfoo(int a)is a function pointer fromfloattoboolfoois a function that takes aintand returns a function pointer fromfloattoboolreally weird in my opinion.
C++ is even worse, due to templates and the so-called most vexing parse. Initializing with
{}mitigated the latter somewhat, but came with its own set of woesMore like getRidOfMyLawn
So that’s why people like C-style return types. That actually makes a lot of sense. I do too now.
To be honest, I think, they both have their place. In Rust, you typically wouldn’t return just a
bool, but rather the element that you removed, so like this:fn getofmylawn(lawn: Lawn) -> Option<Teenager> { lawn.remove() }And then with such a more complex return-type, C-style means that you can’t see the function name right away:
Option<Teenager> getofmylawn(Lawn lawn) { return lawn.remove(); }I also really don’t think, it’s a big deal to move your eyes to the
->…Amusingly, modern C++ allows you to copy the rust signature nearly 1:1:
auto getofmylawn(Lawn lawn) -> Option<Teenager> { return lawn.remove(); }Huh, did that emerge out of unrelated design decisions or did they just figure

I believe that it is useful in a few places. cppreference.com mentions templates as one case:
The syntax also matches that of lambdas, though I’m not sure that adding another way of specifying regular functions actually makes the language more consistent, since most code still uses the old style.
Additionally, the scope of the return type matches the function meaning that you can do
auto my_class::my_function() -> iterator { /* code */ }instead of
my_class::iterator my_class::my_function() { /* code */ }which is kinda nice
Very interesting, thanks! 🙂