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]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.
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, 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. Nonetheless, it annoys me quite a lot. I also 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.