Why didn't Rust go with an easier to read syntax? Why did they stick to old C syntax?
Edit/ Sorry, didn't mean to offend anyone.
Why didn't Rust go with an easier to read syntax? Why did they stick to old C syntax?
Edit/ Sorry, didn't mean to offend anyone.
* Ending statements with ;
* {} for braces, lowercase keywords for control flow
* [] and 0-based indexing for arrays
* Infix operator notation, with mathematical operator precedence
* &, |, ^, ~ for bitwise operators
* . is used for member access
But they didn't copy all of C's syntax:
* There's no ->, since dereference is usually automatic.
* No ?:, if/else can be used as expressions instead
* No ~, since ! on an integer variable does bitwise negation instead.
* Pointer, array, and function types don't have the weird syntax they do in C... you say [ * mut fn()->i32; 4] instead of int ( * ())[4]
* Types follow variables instead of precede them (x: i32 instead of int x)
* No C-style casts (x as i32 instead of (int)x)
So what it should actually be is int ( * [4])(). The principle is that "declaration mimics use" and that a type is written like a declaration with the variable name omitted. So, for an array of pointers to functions mapping no-args to int:
If f is such a function, you would call it as f() and get an int, so the declaration would look like int f() and the type would be int () except that functions, as opposed to function pointers, aren't first-class objects in C and don't have a type.
If pf is a pointer to such a function, you would need ( * pf) instead of f, so the declaration would be int ( * pf)() and the type would be int ( * )().
If apf is an array of those, then you would need to replace pf with apf[something], so the declaration would be int ( * apf[4])() and the type would be int ( * [4])().
Which is, indeed, a bit weird.
(Note: Spaces around all the asterisks because that seems to be the least-bad way of making HN not interpret them as markup. It's quite impressive how damaging HN's markup feature manages to be given how little it's capable of.)
C's function pointer and array syntax does make sense when you understand it, but even for experts, it can be difficult to get it right on the first go.
Well, there is, but it's more like ML’s -> than C’s ->.
We did diverge where we felt it was appropriate.
Off the top of my head, I'd imagine that familiarity for the huge pool of C/C++/Java/C# programmers was probably a huge push for the chosen syntax.
Did they? Rust always seems to me to a pretty free mix of C, Ruby-ish, and ML syntax (and an amazingly well chosen mix, because that description makes me want to run away from it, but the reality is pretty nice.)
The only C style syntax that's used is block grouping (curly braces), and statement separation (semicolon). Unless you go for using whitespace to perform those functions, you're making fairly arbitrary choices about which symbol to use, and those two are familiar.
Most other syntax is really quite different:
* variable definition has a completely different order to it with (optional) type ascription
* function definition has some aspects of C++ (<> for types in generic functions) but much else is different - e.g. position of return type, where clauses, the 'fn' keyword, type ascription
If anything, Rust's syntax can be confusing because the order of names and types are reversed compared to C. This is a trend that a lot of recent languages are returning to because it can simplify the parser.
Also backtick lifetime parameters, but that's a feature that no other mainstream language has, so it was bound to be a little confusing regardless of the syntax.
Of course it has several critical extensions related to impl, generics, lifetimes, references, modules etc, partly influenced by C++ (e.g. generics syntax), Ruby (closure) and Python (self). It depends on your perspective, but if the scope is all programming languages, then Rust is syntactically very close to C.
However "hard to read" is also the many concepts that rust have and certainly the combination of traits/lifetimes make some stuff very obtuse.