I think the thing people don't like about Rust is that it looks vaguely C-like but is clearly not C. People might like it better if it was further removed (aesthetically) from C's syntax. But then they would also complain.
I think there was no way for Rust to meet all its semantic goals and also make people happy about the syntax.
C++ on the other hand also is vaguely C like, but can look equally messy as typical Rust code.
OTH I find Makepad's Rust style very readable, but I can't quite put my finger on it what's different from other Rust code bases:
By removing the ugly "syntax" (and thus also removing important semantics), they're showing that the reason Rust has a lot going on syntactically is because the code is actually expressing important semantics. You can't have a nicer Rust syntax without losing semantics in the process.
var foo []my_struct = {{"foo", 1, "bar"}, {"foo", 1, "bar}, ...}
This is often useful in tests (where each struct value represents a test case). Rust doesn't seem to offer any similarly compact initialization syntax for arrays or Vecs. You have to write some abomination like this: let foo = [MyStruct{a: "foo", b: 1, c: "amp"}, MyStruct{a: "bar", b: 1, c: "fff"}, MyStruct{a: "amp", b: 1, c: "aaa"} ];
Sure, it's more explicit. But even if I add a type annotation to 'foo' specifying the array type, I still have to repeat MyStruct for every member.Since it's a macro there's no impact on runtime performance, but on the other hand it's more work to debug it. Learning declarative macros in Rust is much nicer and safer than learning C macros, but nowhere near as powerful as Rust's horribly unsafe proc macros.
const foos = [("foo", 1, "bar"), ("foo", 1, "bar"), ...];
for (str1, num, str2) in &foos {
// ...
}
For a proper struct you have to name the fields, because otherwise refactoring the fields could cause struct instances to silently get out of sync with the definition.Having to name the fields is only part of the pain. You also have to redundantly repeat the struct name. I don't see any fundamental reason why something like this shouldn't be valid:
let foo: [MyStruct; _] = [{a: "foo", b: 1, c: "amp"}, {a: "bar", b: 1, c: "fff"}, {a: "amp", b: 1, c: "aaa"} ];
I can see the logic for insisting on field names. However, the builtin 'go vet' tool has a nice behavior where it will flag the use of unkeyed literals for public structs only. This strikes me as a good compromise between concision and safety. fn make_struct(x: (&str, u8, &str)) -> MyStruct {
MyStruct { a: x.0, b: x.1, c: x.2 }
}
let foo = [("foo", 1, "amp"), ("bar", 1, "fff"), ("amp", 1, "aaa")]
.map(make_struct);
[I have not actually compiled this code, but it should do roughly what you meant]Rust is more on the verbose/explicit side and I agree that can sometimes be annoying, but as autocompletion exists I can live with it.
There's no reason you couldn't match on struct fields positionally as well. It would actually be quite convenient for cases like struct Point { x: f64, y: f64 }.
Side note: matching f64 by value isn't a good idea either way, is deprecated and will become an error in the future.
I wasn't thinking about matching floats by value, just destructuring a Point to obtain the coordinates as separate variables. Come to think of it though, as Rust already allows
let Point{x, y} = pl
there would be little benefit to allowing positional matching (and in fact it would create a nasty ambiguity). So yeah, as you said, you'd have to reserve the positional syntax for initialisation.My overall point here isn't that Rust has made bad design decisions. It's just that the end result of a bunch of sensible design decisions is that initialising arrays of structs is clunky. It might well be that this problem isn't fixable without creating other, worse, problems. However, I think it's a problem that's emblematic of what the OP was talking about. We have here a language that's so concerned with solving difficult problems in clever ways that it's ended up backed into a corner when it comes to something as ridiculously simple as initialising an array of structs.
Yes, though at least the language gives you tools to make it more convenient. In the previous examples that would be constructors, and macros can help too (`println`, `vec` etc. exist for that reason).
I myself like to create tiny macros to shorten things like `UnicodeSegmentation::graphemes(s, true).count()` when I have to properly handle unicode. Sure I would prefer to have it be shorter from the start, though that wouldn't make it as obvious how expensive the operation is compared to just getting the size in bytes.
I'm really new at Rust, but that was my takeaway, e.g. `String` has `String::new()`
String::new() just makes you an empty String, which, since an empty String doesn't own any storage and doesn't contain anything, is very cheap (and indeed constant evaluable), likewise Vec::new() makes an empty Vec.
What your parent commenter wants is for Rust to make the appropriate MyStruct, but without them needing to say MyStruct each time, which would have worked in e.g. C or Go.