In the interest of boosting ergonomics, this is a proposal to allow conversion from a temporary of type T
to an Option<T>
.
e.g.
fn greet(name: Option<&str>) -> bool {
match name {
Some(n) => println!("Hello, {}", n),
None => println!("Hello, guest!")
}
}
fn main() {
greet("Foo"); //should be converted to temporary Option<&str>
}
Optionally, (and perhaps this should be a separate proposal) greet()
can be interpreted as greet(Option::None)
.
Option<T>
already implements From<T>
(and T: Into<U>
is implemented where U: From<T>
) so you can write code like this:
fn greet<T: Into<Option<&str>>>(name: T) {
let name = name.into();
// …
}
greet("Foo");
greet(Some("Foo"));
greet(None);
Rust is not the average implicit conversions language. Conversions do stuff, so they should in most cases be explicit. (The only exception to this rule is deref coercions, but those are usually work and are implementable trivially.) A From::from()
/ Into::into()
conversion might involve more complicated semantics, e.g. allocating memory, so it should not be completely automatic and silent.
Interpreting a call to fn(Option<T>)
without arguments as calling it with Option::None
is an even worse idea. All these "convenience" syntactic discrepancies end up inducing lots of mental pressure and surprise in readers. Not a good trade-off in a language which is primarily focused on correctness, safety, and robustness. Seriously, None
is already in the prelude, how much does it hurt to write foo(None)
instead of foo()
?
Not to mention that it wouldn't compose either. What if there's a multi-argument function with one of the middle arguments being an Option
? Do you allow fn(T, Option<U>, V)
to be called with two arguments, the second actual argument being bound to the third formal argument? I don't even want to think about this, it's so confusing.
I think this is unlikely to happen; so in the interest of reducing clutter I'll close this.
Feel free to raise the issue on http://internals.rust-lang.org/ if you want to.
Most helpful comment
Option<T>
already implementsFrom<T>
(andT: Into<U>
is implemented whereU: From<T>
) so you can write code like this: