4 ms·
> The idiomatic way to solve that in rust is to re-bind to the same variable name. OK, that's reasonable. Is the idiomatic way to use optionals to introduce a
by matvore 5y ago
> The idiomatic way to solve that in rust is to re-bind to the same variable name.
OK, that's reasonable. Is the idiomatic way to use optionals to introduce a layer of nesting? I prefer keeping functions very "flat"-looking. It sounds like Rust's optionals will give people an excuse to create labyrinthine functions where I'm constantly scrolling around to remind myself of what level of nesting I'm at and whether I'm in a loop or not, etc.
As you say, you don't need a new block to shadow a previous var, so hopefully that style catches on.
> "oh no, this isn't exactly like c, how will anyone ever understand it"
Not very persuasive, sure, but the network effect of the C/C++ culture (including its general syntax and imperative nature) is a strength in and of itself. New languages would do well to coddle the existing C++, Java et. al. users wherever it doesn't contradict the language's central mission.
- iudqnolq 5y ago> I prefer keeping functions very "flat"-looking. I definitely agree. One way I do that is by having an internal function that takes a valid value and a public function that does the validating/error handling. That doesn't always make sense though. There's a few other idiomatic ways to avoid nesting. Since statements evaluate to values, you can write let foo = if let Some(foo) = foo { foo } else { // Something that either evaluates to the same type as foo or returns early } That's so common there's a special operator for it, ?. It essentially either early returns the sad path or evaluates to the happy path. fn get_foo() -> Option<Foo>; fn frob() -> Option<Bar> { let foo = get_foo()?; let bar = convert_to_bar(foo); Some(bar) } I prefer to use Result to model missing data like cases instead of Option because it composes better. So that might be fn get_foo() -> Option<Foo>; fn frob() -> Result<Bar, BarNotFound> { let foo = get_foo().ok_or(BarNotFound)?; let bar = convert_to_bar(foo); Some(bar) } #[derive(Debug, thiserror::Error)] #[error("Bar not found")] struct BarNotFound; That last bit uses a stdlib macro and a very commonly used external lib macro to save a few lines of repetitive typing. Edit: Also ? doesn't special case Result and Option. You can make your own type conform to the interface (trait) it requires. That would probably be weird though.
- matvore 5y agoInteresting. Thank you for sharing.