Earlier quoted context omitted.
How about `let x = 42` and let type inference do the work? I used to do a lot of C-style variable declarations in other languages but I'm warmed up to Rust's really fast because most of the time I don't need to explicitly name the type.
"let" should be removed, and it doesn't change that the type should be placed before, not after with a colon.
A half-hour to learn Rust
41–50 of 150 posts
Re: A half-hour to learn Rust
#42Earlier quoted context omitted.
How about `let x = 42` and let type inference do the work? I used to do a lot of C-style variable declarations in other languages but I'm warmed up to Rust's really fast because most of the time I don't need to explicitly name the type.
"let" should be removed, and it doesn't change that the type should be placed before, not after with a colon.
But there’s a very practical reason for requiring the `let` token: it makes parsing very much easier. With `let`, you can keep a LL(1) grammar, because seeing `let` tells you to next parse a pattern, then if there’s a colon a type after that. But if you don’t put something in there, you get a genuinely intractable problem once type grammar is not trivial: sure, `int foo;` is simple and obvious, but what about `A d;`? should that be parsed as an expression (respaced, `A d;`). Some languages have not resolved this style of parsing ambiguity at all, and figure it out at runtime, based on what else they find (Perl is infamous for this). I think others only kind-of resolve it, by looking at what symbols are present at compile time, to decide what was meant. Others just declare that such ambiguities are parsed one way, and you can rewrite your code (e.g. add parentheses) if you want to mean the other. Still others have resolved it otherwise, by other more subtle syntactic means, so that even if you need arbitrary look-ahead while parsing, there’s not quite any overlap between the two syntaxes (e.g. don’t support commas in this way as a kind of alternative to semicolon within expressions; or use proper matched delimiters like [] or () for generics).
Rust chooses to make parsing simple, which benefits humans as well as machines, reducing cognitive requirements in reading code.
Furthermore, in Rust what follows `let` is not an identifier or identifier list, but rather a pattern. Imagine the following contrived example:
let x = [[0]];
type x = [u32; 1];
let a = 0;
let [a]: x = [1];
That falls over completely if you put the type first: `x [a] = [1];`—does that define a new binding a with value 1, or does it set x[0] to [1]?And finally, as I mentioned, the type is optional, and not commonly required, so you end up with something like C++’s `auto` keyword, which is basically `let` but spelled worse (and with worse semantics).
The end result is that for Rust specifically, what you desire is quite unsuitable, and what it has works very well—and that its reasons for doing things that way are well worth while considering.
Re: A half-hour to learn Rust
#43> let x: i32 = 42; I'm sorry but this notation will always make me scream. C is so much simple: int x = 42; not "let", no colon, and no ambiguous "i32 = 42"
int[4] arr; // oops, doesn’t compile
Or a function pointer: int (*)(int) fptr; // oops, doesn’t compile
So much for the simplicity of C declaration syntax.Re: A half-hour to learn Rust
#44The Haskell community once was flooded with Monad tutorials[1]. People kept trying to put meanings on this mathematical construct, and had come up with tons of different ways to describe it. The problem is, this simple thing can fit into so many different places, so people couldn't possibly run out of new ideas. This oversaturation only confused newcomers even more, so the community concluded not to write any more Monad tutorials.
While individual tutorials enrich the community in general, it's more crucial to have a few good documentation that kill the need for more tutorials (e.g. MDN + W3School), so that efforts can be redirected into more productive things. Rustonomicon is one good documentation, but it always falls few steps short in practice. That's probably why more tutorials are being written, and why they get upvoted well in both HN and Reddit.
Re: A half-hour to learn Rust
#45> let x: i32 = 42; I'm sorry but this notation will always make me scream. C is so much simple: int x = 42; not "let", no colon, and no ambiguous "i32 = 42"
The C approach makes the compiler much more complex, and introduces extra typing in other language constructs. (like parens around if statements) This is why many newer languages do something more like the Rust way. Overall it is simpler for programmer and compiler.
Re: A half-hour to learn Rust
#46Numbers could also be differentiated in Rust. For example, to make sure your "16" is an i32 you could write > let x: i32 = 16i32; Otherwise, it's a very comprehensive article. The only missing parts are the async/await keywords and the sync primitives (like Mutexes/RwLocks).
C# has a similar feature, but it's less verbose, e.g. "16l"/"16L" is a long (64-bit integer), "16u" is an unsigned, 32-bit integer etc. I find the rust syntax a little difficult to read. Take "16i32" for example - it's not immediately clear which part is the actual value.
0xFFFF_FFFF // easier to count than 8 Fs
And you can use that with type suffixes: let a = 255_u8;
Although in that case, you'd probably either omit u8 entirely, letting the compiler infer the type of 'a' from usage, or use a colon to give it ane explicit type.Type suffixes are especially useful for arguments to generic functions:
write_le(12_u32);
write_le(255_u8);Re: A half-hour to learn Rust
#47how much Mozilla paid for this article?
Re: A half-hour to learn Rust
#48Earlier quoted context omitted.
A valid point about knowing what the types mean, but even if you don't, it is at least immediately apparent which part is the type , and which part is the value . I've only dabbled with rust, but I came across this very early on, and was baffled by the syntax. After further dabbling, I still can't see it and immediately know what the value is.
AFAIK, syntax is: let variable_name [: type] = value[(i|u|f)bits]; In rust, 123l is written 123i64 or 123i32 (also 123_i32, or 1_2_3i32), depending on what 123l actually means. I don't actually use rust, but it seems very clear and obvious to me (obvious once you know the syntax above).
let (a, b) = some_two_tuple;
will introduce two varaibles, a and b, as respective halves of the tuple.Re: A half-hour to learn Rust
#49> let x: i32 = 42; I'm sorry but this notation will always make me scream. C is so much simple: int x = 42; not "let", no colon, and no ambiguous "i32 = 42"
int foo = 42;
but doing the same thing for pointers to arrays or function pointers is not:
void(foo)(int) = bar; // function pointer
int (foo)[N] = baz; // pointer to array
OTOH in Rust you just need to learn one rule: bindings are created with the grammar "PATTERN [: TYPE]" ([] means the ":TYPE" is optional.
That's the only rule you need to know: (1) it works consistently everywhere in the language (let, match, for, if-let, function arguments, while-let...), (2) it lets you create bindings, and (3) it gives you pattern matching and destructuring for free. For example,
let x: i32 = 42; let y: fn(i32) = foo; let z: \const [i32] = bar;
but also:
struct Entity { id: i32, vel: (f32, f32) }
let e: Entity; // given
let Entity { vel .. } = e; // vel points to e.vel
let Entity { vel: (v_x, ..), .. } = e; // v_x points to e.vel.x;
// Works in function arguments:
fn foo(Entitiy { vel, .. }: Entity) -> (f32, f32) { vel }
// Works in for loops:
for Entitiy { id, .. } in entities() {
// use the id of the entity
}match entity { Entity { vel: (v_x, ..), .. } if v_x > 0 => {
// do something if the entity.vel.x > 0
}
_ => /* do something else otherwise */
}etc.
That's IMO the definition of efficiency: one simple rule, that has no exceptions, works everywhere, and lets you do a lot.
What C does of having multiple different incompatible rules, some for doing simple things like "int a = 42;" and some for doing complex things like "void (foo)(int) = bar" is not simple. It's just a pain. It means that professional C programmers need to look up rules for things they don't use as often, which is why Stackoverflow is full with questions about "How do I assign a function pointer to a variable in C?", "How do I pass a function pointer as a function argument in C?", etc. Having to learn multiple rules to do the same thing just sucks, and is one of the main reasons I love using Rust: when I learn something, I learn it only once, and things I learn later just reinforce that I learned it in the right way.
Re: A half-hour to learn Rust
#50Be warned, the "half hour" part is probably a bit like "99 cents" as a price tag. I've already spent more than that, but it is time well spent.
Thanks for writing this!