DEV Community

Discussion on: Are there functions similar to Ruby's `dig` in other languages?

Collapse
 
brightone profile image
Oleksii Filonenko • Edited

I'm currently doing Rust, and I have a little trouble answering this question.

A couple points:

  • Rust does not have anything like dig built-in.
  • It wouldn't make sense, as there is no nil/null/whatever in Rust - if it's a String, it's there, no strings attached (pun intended).
  • To represent a value that might not be there, there is a concept of an Option enum, which can be either Some(value) or None (the concept is not new - Haskell has Maybe, and languages like Swift or Kotlin have nullable types)
  • A macro can probably do something like that for nested Options.

I came up with this:

macro_rules! dig {
   ( $root:ident, $($step:ident),+ $(,)? ) => {
      {
         let leaf = $root;
         $(
            let leaf = leaf.and_then(|inner| inner.$step);
         )+
         leaf
      }
   }
}

Looks a bit funky, but does the job:

let c = Some(C {                                   
    b: Some(B {                                    
        a: Some(A { data: 5 }),                    
    }),                                            
});                                                
assert_eq!(Some(5), dig!(c, b, a).map(|a| a.data));

let c = Some(C { b: None });                    
assert_eq!(None, dig!(c, b, a).map(|a| a.data));

EDIT: I completely forgot about a cool language feature in Rust - ? operator.

Synopsis:

Result<T, E> is very similar to Option<T>, but it instead can be either Ok(T) (all good, T is the value) or Err(E) (something went wrong, E is the error type - String for a message, etc.)

result? basically means .if it's Ok, get the inner value and continue execution. If it's an Err, return it".

It allows for code like this:

fn etl(data: ...) -> Result<..., Error> {
    data.extract()?.transform()?.load()
}