While working with serde_json for reading json documents, I wrote the following line of code to obtain the result of unwrapping the return value of serde_json::from_str
:
fn get_json_content(content_s: &str) -> Option<Value> {
let ms: String = serde_json::from_str(content_s).unwrap; // <--
match serde_json::from_str(content_s) {
Ok(some_value) => Some(some_value),
Err(_) => None
}
}
As you can see, I forgot the ()
on the end of the call to unwrap
, which resulted in the following error:
error: attempted to take value of method
unwrap
on typecore::result::Result<_, serde_json::error::Error>
let ms: String = serde_json::from_str(content_s).unwrap;
But when I looked at this a bit further, the thing that struck me as odd was:
core::result::Result<_, serde_json::error::Error>
I understand what underscore means in a match context, but to instantiate a generic? So what does this mean? I couldn't find any answers in the Rust book, or reference, or a web search.
In Rust, generics refer to the parameterization of data types and traits. Generics allows to write more concise and clean code by reducing code duplication and providing type-safety. The concept of Generics can be applied to methods, functions, structures, enumerations, collections and traits.
Rust can make use of generics in several places: Function Definitions. Struct Definitions. Enum Definitions.
It means "Rust compiler, infer what type goes into the Vec ". And it is indeed analogous to the unused variable in Python (and in Rust itself), in that it represents a placeholder for a type, like it can represent a placeholder for a variable name.
It's a placeholder. In this context, it means that there isn't enough information for the compiler to infer a type.
You can use this in your code to make the compiler infer the type for you. For example:
pub fn main() {
let letters: Vec<_> = vec!["a", "b", "c"]; // Vec<&str>
}
This is particularly handy because in many cases you can avoid using the "turbofish operator":
fn main() {
let bar = [1, 2, 3];
let foos = bar.iter()
.map(|x| format!("{}", x))
.collect::<Vec<String>>(); // <-- the turbofish
}
vs
fn main() {
let bar = [1, 2, 3];
let foos: Vec<_> = bar // <-- specify a type and use '_' to make the compiler
// figure the element type out
.iter()
.map(|x| format!("{}", x))
.collect(); // <-- no more turbofish
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With