I can assure you that Rust's syntax is not designed to further separate application development from system development, if anything, we encourage a way broader audience to learn Rust than just pure systems programmer folks. In general, Rust's syntax is intended to be vaguely similar to C/C++/Java, but with some influence from functional languages where appropriate, and with syntactic forms that work better with type inference. There is very few syntactic forms that are truly novel in Rust (even lifetimes are taken from OCaml's generic syntax, because lifetimes are generics!)
In addition to this excellent reply, if you were using the type core::panic::PanicInfo commonly (i.e. "twice") you would import PanicInfo at the top of the file
Yes, and you can do something similar with C++ too; I debated if I should include it or not for this reason. (The semantics are a bit different...) Thanks for bringing it up!
In C++ unary prefix & is used in an expression to take the address of an object. To declare a parameter of reference type the & would be between the type name and the parameter name (i.e. after PanicInfo/before _info).
> "name: type" not "type name", which adds a single :
Sorry for asking a newbie question that's a quick search away, but is there an equivalent to "type name, name, name..."? (I'm biased towards C myself but contemplating a switch...)
Rust’s pattern syntax is richer than just introducing variables. I’m on my phone, so it’s a bit hard to show off all of the things that can be done. In this exact case, though, it usually looks like
One reason is that overriding "=" would allow you to violate the move semantics of Rust: a = b; is guaranteed to be equivalent to memcpy(&b, &a, sizeof(a)). In C++, you can overload the assignment operator, which lets you do crazy, unexpected things. In the end, it's mostly a tradeoff between convenience (writing a = b; instead of a.assign_from(b);) and explicitness (being able to tell what might and what might not happen under the hood).
It's the difference between the Copy and Clone traits. One thing that Rust still lacks in its standard library is a Clone-like trait for moving data, which is also something that C++ can express, and could be useful in combination with "pinned" object which can't be memcpy'd. There is a crate providing this (via a Transfer trait), but it's nowhere near being a standard.
If this were ever to happen, it would have to be similar to Clone in that it would be explicit, not implicit. This would also make it not as useful as the C++ version, but it means not giving up all of the advantages of our semantics.
Because `fn foo() u8 {}` doesn't read as nicely as `fn foo() -> u8 {}`?
Also because "no return type" is the most common return type, and this way representing "no return type" as omitting the `-> ()` reads nicely: `fn foo() {}`
I think that the advantage of leading with `fn` arrives when you have paragraphs of functions to scan through.
Leading with a consistent word (be it fn, func, or whatever) immediately and disambiguously identifies the line as defining a function (rather than a variable, or whatever), which is a useful landmark to anchor on or pivot from.
So, using grep or a similar tool, how would you find the definition of the function, separately from its uses? In a Rust codebase I could just run `grep -r "fn foo" .` and find the definition immediately.
Clearly this doesn’t matter if you’re in an IDE with a working “find definition” feature, but that’s often enough not the case that I find easily greppable definitions to be a gigantic advantage.
We could have, and discussed it, but IIRC there's some good reasons why we didn't. That was a very long time ago and I don't quite remember them now, though... I think that the idea is that this gets ambiguous with type ascription?
I'm not sure of the historical context, but it would have required either for the syntax to declare the return type of closures to be different from functions or for type ascription to have a different syntax.
To be honest, type ascription being : was a (small) mistake that affects the comprehensibility of errors because it is distance 1 from multiple common typos and is valid almost everywhere in the grammar, so it is very easy for the parser to go down the wrong route. Even worse, the feature is nightly only so we're not even getting the benefits of the simple syntax.
Advice for language designers: make your grammar redundant, with lots of sign posts for the compiler to recover when things are wrong. Things like mandatory semicolons are good for both humans when reading code and for the compiler when parsing it. You can also make your compiler perform semicolon autoinsertion, but still have an error, that way the type checker can still run.
That said,
would be something like in C++, which is very similar, syntactically speaking. The main differences are:* fn for function declarations
* Rust has the return type after parameter list, and adds ->
* ! is [[ noreturn ]], less punctuation actually!
* no need for the superflous void return type
* "name: type" not "type name", which adds a single :
I am admittedly very biased, but it seems much more similar than different.