I think it would be useful to have Option::unwrap_or_from and Result::unwrap_or_from methods, which call From::from on the fallback value if the value is None/Err.
For example, if you have an Option<String>, you could write
let _: String = option.unwrap_or_from("default value");
which would be equivalent to
let _: String = option.unwrap_or_else(|| String::from("default value"));
Do you think it's justified to add this to the standard library? Also, do you think that unwrap_or_into would be a better name?
String and Vec are the most common use cases I think. To get some data, I just cloned the rustc repository and searched for .unwrap_or_else(. Ripgrep found 430 usages, and at least 37 of them could be trivially converted to unwrap_or_from (ignoring the ones that could just use unwrap_or). That's fewer than I expected though.
In such a case the type to convert into should always be known to the compiler, so you could write the shorter option.unwrap_or_else(|| "default value".into()) which is a fairer syntactic comparison.
This thread makes me wonder if there’s a strong reason against having
impl<T, F: FnOnce() -> T> From<F> for T {
fn from(f: F) -> T { f() }
}
in the standard library. Then one could change unwrap_or_else (and lots of other API accepting Fn() -> T parameters) to be more general and wouldn’t need an additional unwrap_or_from. This would unfortunately, probably both would things technically be breaking changes though.
Edit: Damn it, it conflicts with From<T> for T for some reason.
Yeah, I actually know that that's the conflict there, but it's a conflict that realistically should never happen.
Currently Fn-traits are still unstable, so it's actually impossible to get competing impls here, since a closure or fn will never have itself as Output. This means that if we would get some negative-impl feature or something else enabling us to prevent T: FnOnce<(), Output = T> (i.e. T: FnOnce() -> T) before stabilizing Fn-traits, then this conflict might still be possible to resolve.
Edit: A bigger problem might be that we can already do some impl From(fn() -> MyType) for MyType instances currently, so that this whole idea becomes backwards-incompatible.
I think the biggest problem with this proposal is that taking it further would imply the need to add unwrap_or_else_xyz for all kinds of common traits with method xyz and each for both Option and Result, and all that just to be able to write my_val.unwrap_or_else_xyz(foo) instead of my_val.unwrap_or_else(||foo.xyz()).
Under this naming scheme unwrap_or_from would be called unwrap_or_else_into.
Hence, you could propose unwrap_or_else_to_owned next, and then unwrap_or_else_to_string and so on.
I don't like heap-allocating string literals when it's avoidable, so I prefer converting the other way. This already works, and if you don't need the owned type, it's more efficient too:
let s: &str = string_option.as_deref().unwrap_or("default value");