-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement From<T>
for Option<T>
#1402
Comments
The main objection, I can see, is that you'll now have multiple ways of converting |
👍 This is actually pretty cool. |
This looks pretty convenient! The only issue I can see is that APIs will be harder to read, just compare fn set_timeout(&mut self, timeout: Option<u64>); and fn set_timeout<T: Into<Option<u64>>(&mut self, timeout: T); (But that's probably something that rustdoc could be optimised for.) |
The ergonomics could be improved with an alias of some sort, like type IntoOpt<T> = Into<Option<T>>; |
That reads a bit nicer, @cybergeek94, but doesn't really solve the problem that the significant type information is no longer part in the function's argument as the ( |
I don't know if it's that big of an issue, at least for most intermediate to advanced users. Whenever I see a type parameter in documentation or code, my eyes instantly jump to the type parameter list to find its definition, and then to the |
I, too, don't think that's a problem. You quickly get used to it. |
I didn't mean to imply it's a big issue, just something to be aware of. Beginners are often confused by the notion of In general, I'm in favour of this addition. |
@killercup If we did go with the trait alias, we could have additional documentation on it saying what it is for, so they could click the link in Rustdoc output and instantly find out how it's supposed to work. |
Not an objection or anything…but, in case no one's noticed, this basically gives Rust (opt-in) nullable types. |
@BlacklightShining shh.... 😶 |
@Stebalien I'm conflicted, actually. On the one hand, The decrease in readability is also something to consider. Did we already decide against allowing traits there? |
Coming back to this after two weeks, I'm still in favour of this. While it makes designing the API a bit more complicated for library authors, it makes the code using the API pretty nice to read and write. I think it works pretty good for people coming from languages with null-able types: You can pass Other than that, I've been searching for APIs where this would be useful (i.e., functions that actually take What are some other APIs where this would be useful? |
There are a few APIs in nix that could benefit. We aim to take |
This allows improved ergonomics for functions that have optional parameters: instead of taking `Option<T>`, they can have a type parameter bounded by `Into<Option<T>>`. That way, a value of type `T` can be passed directly without being wrapped by `Some`. As an example, a function fn foo<T>(required: i32, optional: T) -> i32 where T: Into<Option<i32>> { required + optional.into().unwrap_or(0) } can be called as `foo(2, None)` or as `foo(2, 3)`. Refs rust-lang/rfcs#1402
@kamalmarhubi Does it need to be the |
@bluss is there a reason you're concerned about the use of the |
Changes to From/Into impact everyone's API design (also preexisting APIs) so it needs close scrutiny. Using the same From/Into traits for everything just means we risk having conflicts down the line when independently convenient conversions clash. A specific trait seems more in line with Rust's explicitness and may even be an easier to understand API. fn ping<T>(host: &str, timeout: T) where T: Optional<i32> { }
// where both i32 and Option<i32> implement Optional<i32>. |
@bluss there's no strong reason, and I'd be open to something like
|
The problem with nullable types is handling them once you have them. Needing to convert a type into its optional version explicitly doesn't really help anything, except that |
@notriddle You can pass a |
I don't think you'd be able to pass |
Can this now be closed? |
This is a trivial impl and I think it would help ergonomics in certain areas of API design. As an example, consider a method on a fictional I/O wrapper for setting a timeout:
This can be called in both of the following forms without needing separate methods for
u64
andOption<u64>
:Currently, if this API wanted to take an
Option<u64>
, it would have to be invariant over it:Requiring
Some
everywhere:I think the above is much cleaner.
There are existing APIs such as the following:
http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_read_timeout
which I think could be migrated relatively seamlessly. I think the only breakage would be if someone was referring to them by UFCS, so the addition of a type parameter would break resolution (maybe). A Crater run would probably help here.
Otherwise, I don't see much as far as downsides go, except maybe some brief confusion for newbies. However, I don't think it would take them long to realize, "Oh! It can take
u64
orOption<u64>
. Cool!" Then it's just another neat little feature of Rust. I don't think accidental conversions would be a problem, either.The text was updated successfully, but these errors were encountered: