This post is long for a simple question, but a large goal here is to demonstrate what I have personally felt is a significant pain point that didn’t have to be.
I am a Rust beginner who was attracted to Rust by its language features. Most notably these:
Memory Safety without a GC
Composition-based structure via Traits
I come primarily from a C# background (though I wrote c++ an age ago).
I recognize that the biggest need for Rust is found in embedded systems where people are tired of the long legacy of problems with C. That being said, I personally felt attracted to Rust because I would like to write more native code without having to go to a language that makes it easy to hang yourself. Even though I pride myself on clean code with minimal bugs and could get by in C++ myself, as a developer who manages other programmers, Rust is even more valuable to me because I can more safely count on junior programmers not writing memory-leaking crud.
The overall point being that Rust seems very attractive to someone from a Java or .NET world because we can say goodbye to the garbage collector, while gaining other benefits like the Trait-based architecture and (my favorite) zero-cost abstraction.
But I have a couple of hangups with the syntax and readability. And even though, I can look past them to see the genius of Rust, I believe the syntax is going to drag down development by developers who might otherwise get along in an easier-to-read language like C#.
My single biggest question is “why are the function definitions reversed?” and moreover, what’s the point of the “fn” keyword? I can’t see what’s wrong with the C, C#, and Java way of doing things where the function leads with its return type (google agrees. Look at Dart).
On my team, I insist on readable code, and I make sure my team members steer away from over-zealous use of “var” keyword in c#. I want clearly defined Types that imply intent and improve readability in statements, expressions, and functions. When a reader scans code, their eyes anchor to the left of the lines, which means you need the most important information located at the left. In my experience, function return types and their name tell you more about what a function actaully does than its input parameters. To read Rust functions fast, you have to read the function name and then jump over to the right side of the line to see the return in order to find out what the function’s overall objective is. That’s not fast to scan and ingest.
Now maybe others disagree with me, but to me after reading code for years and doing code review with junior developres, this seems like it should be painfully obvious. Moreover, C#, C, and Java all define functions this way and those three languages together make up the lion’s share of development. And to further support the belief in their design, just take a look at Dart. Google is betting the farm on Dart and Dart reads almost verbatim like C# or Java. I think Dart has an enormous furture ahead of it, and with more and more programmers moving to another language with C-like syntax, I’m sitting here wondering if Rust has created for itself an unnecessary uphill battle with the way it defines its most basic feature: a function.
Of course, many people may read this and think this absurd and I should be drinking the Rust kool-aid without any complaints. We can all look past the “shape” and “arrangement” of function definitions and accept their reversed order. But, the science of ergonomics says that’s a recipe for nothing but problems – and why should it be so? Did the function definitions really have to be reversed from the most commonly used languages?
Its quite possible everything I’ve written here is going to be met with a really darn good reason for why the function definitions are backwards, but I have yet to figure it out from hypothetical guessing.
Let me address my other syntax hangup for a moment – a hangup which I fully accept and see as merited:
I hate the “let” keyword, but after some guessing I did figure out that the use of let must be an ergonomic decision to force Rust developers to write sound code.
I personally would rather see an “imm” keyword for immutable and abolish “let” completely. So code would be written like this:
imm x = 1;
mut x = 1;
instead of this:
let x = 1;
let mut x = 1;
However, I see the line-of-thinking as an ergonomic choice of let. Because “let x” takes fewer keystrokes to type, deveopers will naturally favor grabbing it before reaching for “let mut x”, which means developers will be inclined to define immutable variables first and only make them mutable where necessary. This is pretty clever. I think its ugly as sin to read, but during the writing process it does encourage good code design.
That being said, I’m sitting here guessing there must be some similar design reason for why functions start with “fn” (which tells me absolutely nothing useful) and end with the return type. But I can’t figure out what the reason is.
Can anyone shed some light on this?
p.s. I’m sorry for the long post. And I’ll reiterate that I love Rust’s core design principles – they’re amazing! But I want it to be more readable (especially during code review) – and I feel like its lacking in that area.