MikeB
MikeB

Reputation: 948

How to fmt an Option<String>

I just want to include something optional in a format expression, each time I do it I end up finding a different way because I haven't found one I'm happy with.

// here's the most basic form, when it works, it's great
let o: Option<&str> = Some("some");
assert_eq!(
    format!("format {}", o.unwrap_or_default()), 
    "format some");

// unfortunately, if `o: !Copy` that would consume `o`, which I might not want so it becomes a bit longer
let o: Option<String> = Some("some".to_string());
assert_eq!(
    format!("format {}", o.as_ref().map(String::as_str).unwrap_or_default()), 
    "format some");

// if I want to get rid of that extra space on `None` then it becomes really ugly
let o: Option<String> = None;
assert_eq!(
    format!("format{}", o.as_ref().map(|s| format!(" {}", s)).as_ref().map(String::as_str).unwrap_or_default()), 
    "format");

rust playground

Upvotes: 2

Views: 2460

Answers (1)

prog-fh
prog-fh

Reputation: 16925

With as_deref() it does not seem to be consumed.

#[derive(Debug)]
struct Thing {
    value: i32,
}

impl Default for Thing {
    fn default() -> Self {
        Self { value: -1 }
    }
}

impl Default for &Thing {
    fn default() -> Self {
        &Thing { value: -1 }
    }
}

fn main() {
    let a: Option<&str> = Some("some &str");
    println!("1: {:?}", a.as_deref().unwrap_or_default());
    println!("2: {:?}", a);
    let b: Option<&str> = None;
    println!("1: {:?}", b.as_deref().unwrap_or_default());
    println!("2: {:?}", b);
    let c: Option<String> = Some("some String".to_owned());
    println!("1: {:?}", c.as_deref().unwrap_or_default());
    println!("2: {:?}", c);
    let d: Option<String> = None;
    println!("1: {:?}", d.as_deref().unwrap_or_default());
    println!("2: {:?}", d);
    let e: Option<Thing> = Some(Thing { value: 123 });
    println!("1: {:?}", e.as_ref().as_deref().unwrap_or_default());
    println!("2: {:?}", e);
    let f: Option<Thing> = None;
    println!("1: {:?}", f.as_ref().as_deref().unwrap_or_default());
    println!("2: {:?}", f);
}
/*
1: "some &str"
2: Some("some &str")
1: ""
2: None
1: "some String"
2: Some("some String")
1: ""
2: None
1: Thing { value: 123 }
2: Some(Thing { value: 123 })
1: Thing { value: -1 }
2: None
*/

Upvotes: 2

Related Questions