Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a shortcut for as_ref().unwrap()?

In my code I have a lot of structs with Option<T>s in them. I need to work with them in a lot of places, so my code is littered with struct accesses like car.engine.as_ref().unwrap(). This is pain for code readability.

Is there a default function on the Option<T> type that does the same? Like car.engine.get()? Of course I could write accessor functions for every struct member, but this seems like an overkill for something so basic. Am I doing it wrong?

I don't know much about macros, but is there a way to shorten it with macros?

like image 419
itmuckel Avatar asked Nov 30 '17 09:11

itmuckel


2 Answers

You might be able to take advantage of the ? operator that (since Rust 1.22) also works with the Option<T> type (like it does with Result<T, E>):

struct Foo;

struct Bar {
    foo: Option<Foo>,
    // other optional fields
}

impl Bar {
    fn use_optional_fields(&self) -> Option<&Foo> {
        let foo = self.foo.as_ref()?;
        // use optional fields
        Some(foo)
    }
}
like image 75
ljedrz Avatar answered Nov 19 '22 04:11

ljedrz


I can't find anything like that, which is not surprising, since unwrap is generally discouraged anyway. If you want to handle the error case, you can do this:

if let Some(ref e) = car.engine { println!("foo {}", e.serial); }
else { println!("nope"); }

Otherwise, you can easily write your own function thanks to extension traits:

trait OptionExt {
  type Value;
  fn unwrap_ref(&self) -> &Self::Value;
  fn unwrap_mut(&mut self) -> &mut Self::Value;
}

impl <T> OptionExt for Option<T> {
  type Value = T;
  fn unwrap_ref(&self) -> &T { self.as_ref().unwrap() }
  fn unwrap_mut(&mut self) -> &mut T { self.as_mut().unwrap() }
}

// Now you can write
let e = car.engine.unwrap_ref();
like image 21
Sebastian Redl Avatar answered Nov 19 '22 02:11

Sebastian Redl