In my limited rust experience, I’ve found that it does a pretty good job of using the ugliness of something like an explicit lifetime to signal to the developer and reader that the code is doing something complicated and non-obvious. Like “here’s a part where the types logic required more help than what the compiler could figure out on its own; here be dragons.”
In that way the “ugliness” is really just a manifestation of “hard things possible” and the language not hiding the underlying realities from you.
It is of course impossible to know the context in which you saw this, but I will say this is a particular idiomatic way to write Rust which won't mesh with your C knowledge.
Also this code isn't a thing you'd actually do, it's maybe an illustration or part of an example I suppose
You see that vec![1, 2, 3] ? That's what we're getting at the end, a growable array with three integers in it. All the other stuff is machinery to handle errors which in fact have not happened.
let flattened = vec![1, 2, 3];
Is the same effect, although probably for style you'd write:
It's a bit unusual for a type to be wrapped in both an option and a result, since they have a lot of overlap. They're both union types, but semantically, Result takes the place of throwing an exception (Ok is your return value or here's the error) while Option takes the place of a pointer (Some is an instance of the underlying type, vs None which the null case).
Normally these union types would be handled with a match, or an if let, eg:
if let Some(x) = fn_returning_an_option() {
do_thing_with_x(x);
} else {
// handle that it was none
}
The unwrap functions are basically just shortcuts for this, with the most extreme being unwrap() itself, which simply returns the Ok/Some value if present, and otherwise triggers a panic state resulting in the program exiting.
But all of this is rust forcing the developer to either address the null case, or explicitly put in an "unwrap" to acknowledge that they're not addressing it. This is in contrast to C or C++ where you just myPtr->lol wherever you want, and if myPtr is null then it's a segfault.
So that's the worst of it. The rest is the function chain, which is a bit obscured by lack of indentation, and that the functions are being passed lambdas.
Some of my complaints are petty, and I think can be dismissed as just personal preference. I don't have a great deal of complaint with languages with different syntax, just ones that are so intentionally cryptic so as to invent needless specific sigils that you need to memorize.
I agree that most of the awkwardness of reading comes from explicit declarations, but really, even if it's more verbose, I would prefer that that explicit nature is defined elsewhere rather than reading like a compact run-on sentence. (I'm hypocritically writing here, since I do this too often myself.)
> just ones that are so intentionally cryptic so as to invent needless specific sigils that you need to memorize.
Can you back up this claim that the language is intentionally cryptic?
Ignoring that: other languages have sigils (Perl's @, $, %, etc.; PHP has always used $; Java uses @ annotations, and so on) or their own quirky syntax (C#'s custom attributes before a class, Python's @ decorators, etc.). What is it about Rust that is particularly confusing?
As in the prior comment, I'm a relative novice myself and certainly never achieved that moment with Rust where the code kind of melts away and you just see raw intent ("blonde, blunette, redhead"), but I do wonder if languages like Python have set our expectations a bit unrealistically in regards to that. Like instead of prioritizing information density, explicitness, and clarity, we got excited about the quick rush that came with `import antigravity`.
Java and C++ aren't just verbose, there's a lot of redundancy there, at least classically. Stuff that is needlessly repeated between headers and implementation, cases where you're having to hold the compiler's hand and continually repeat information that it should be able to infer itself from the code. And then the moment you find auto or template inference and feel like you can finally trust the compiler to do the right thing, it barfs up half a page of inscrutable errors and you're back to babying it.
Rust—in my limited exposure—is hitting kind of a sweet spot where it's the expressiveness and build/package ecosystem of Python, the performance and precision of C++, and the density of Perl. Or at least that's what's being aimed for; but obviously these goals open it up to charges that it's actually just as unreadable as Perl or as verbose as C++.
In my limited rust experience, I’ve found that it does a pretty good job of using the ugliness of something like an explicit lifetime to signal to the developer and reader that the code is doing something complicated and non-obvious. Like “here’s a part where the types logic required more help than what the compiler could figure out on its own; here be dragons.”
In that way the “ugliness” is really just a manifestation of “hard things possible” and the language not hiding the underlying realities from you.