3 ms·
Awesome article, but I'm stuck on the "error-double-string" example: ... argv.nth(1) .ok_or("Please give at least one argument".into())
by 1_player 11y ago
Awesome article, but I'm stuck on the "error-double-string" example:
...
argv.nth(1)
.ok_or("Please give at least one argument".into())
.and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string()))
...
What is str::into? I find the documentation is really hard to navigate for a Rust newbie like me: here's what I've tried:
1) Search "into" on the API docs. I find (https://doc.rust-lang.org/std/convert/trait.Into.html#tymethod.into https://doc.rust-lang.org/std/convert/trait.Into.html#tymeth...) and see that str implements this trait to convert it to a Vec<u8>. Not seeing the need for a conversion to Vec<u8> I...
2) Search "ok_or": I find (https://doc.rust-lang.org/core/option/enum.Option.html#method.ok_or https://doc.rust-lang.org/core/option/enum.Option.html#metho...) but I still don't see why the string has to be converted to Vec<u8>.
3) Maybe literal strings are Vec<u8> and into() just is used to convert a Vec<u8> to str. Can't find any documentation on that, and seems fishy if it were the case.
4) Try googling "rust str into" with useless results. Not Rust's fault here :)
I haven't used Rust yet but often try to read other people code and understand what's going on, and everytime I hit the API docs I'm filled with despair that I can't find what a function is supposed to do.
Again, I'm a noob. I must be doing something wrong..
- steveklabnik 11y agoOne thing you can do when you're confused about a type is to remove the call, and see what happens: error: mismatched types: expected `core::result::Result<_, &str>`, found `core::result::Result<i32, collections::string::String>` (expected &-ptr, found struct `collections::string::String`) [E0308] hello.rs:6 .and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string())) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hello.rs:6:25: 6:74 help: pass `--explain E0308` to see a detailed explanation In other words, without the call to `into()`, we expected a &str, but got a String. This `into()` call is the first one that you found, but, through some magic, it's not clearly obvious, it's true. The secret is Into's opposite, From: https://doc.rust-lang.org/std/convert/trait.From.html https://doc.rust-lang.org/std/convert/trait.From.html There's a generic implementation in the standard library: impl<T, U> Into<U> for T where U: From<T> { In other words, anything that implements From, implements Into as well. So generally, things just implement From, and take advantage of this blanket implementation. With this knowledge, this From implementation makes sense: impl<'a> From<&'a str> for String We can convert From a String to a &str, and hence, we can convert a &str Into a String. This kind of type shenanigans is _very_ powerful, but admittedly, a bit confusing.
- 1_player 11y agoSo "foo".into() could be expressed as String::from("foo") I would personally use the latter form as it is easier to parse and reason about. Thanks for the explanation!
- steveklabnik 11y agoYup! Yeah, it really depends on your style. Rust tends to prefer methods to free functions, due to multi-dispatch, but there's a good argument for either style. Furthermore, there's a non-generic version of this particular conversion: "foo".to_string() And, a generic version that expresses a different semantic: "foo".to_owned() Strings are a very common type, and so implement a _lot_ of these things, even when this kind of usecase may overlap.
- Veedrac 11y ago> Strings are a very common type, and so implement a _lot_ of these things, even when this kind of usecase may overlap. I can't say this is very helpful; it's hard enough learning the one way. Why have `to_string()` if we have `into()`?
- steveklabnik 11y agoWell, one reason is that to_string() is ancient, but into() is fairly new. Another is that 'to' and 'into' are two different things: to_string() takes its caller by reference, and produces a copy. into() takes its caller by value, and so consumes it.
- burntsushi 11y ago> I haven't used Rust yet but often try to read other people code and understand what's going on, and everytime I hit the API docs I'm filled with despair that I can't find what a function is supposed to do. Please don't think this way! Steve already answered the technical question brilliantly, but the Rust docs can be very difficult for newcomers to navigate. I don't think we've found a really good way of making unknown unknowns easily discoverable. The `into` example here, for a new comer, is particular is tricky because it requires reasoning about very generic conversion traits. It's hard to know that without, well, knowing it!