官术网_书友最值得收藏!

Using generics

Now, the way we instantiate or use generic types is also a bit different than their non-generic counterparts. Any time we instantiate them, the compiler needs to know the concrete type in place of T in their type, signature, which gives it the type information to monomorphize the generic code. Most of the time, the concrete type is inferred based on the instantiation of the type or by calling any method that takes a concrete type in the case of generic functions. In rare cases, we need to help the compiler by specifically typing out the concrete type in place of the generic type by using the turbofish (::<>) operator. We'll see how that is used in a moment.

Let's look at the case of instantiating Vec<T>, a generic type. Without any type signature, the following code does not compile:

// creating_generic_vec.rs

fn main() {
let a = Vec::new();
}

Compiling the preceding code, gives the following error:

This is because the compiler doesn't know what type a would contain until we specify it manually or call one of its methods, thereby passing in a concrete value. This is shown in the following snippet:

// using_generic_vec.rs

fn main() {
// providing a type
let v1: Vec<u8> = Vec::new();

// or calling method
let mut v2 = Vec::new();
v2.push(2); // v2 is now Vec<i32>

// or using turbofish
let v3 = Vec::<u8>::new(); // not so readable
}

In the second code snippet, we specified the type of v1 to be a Vec of u8, and it compiles fine. Another way, as with v2, is to call a method that accepts any concrete type. After the push method call, the compiler can infer that v2 is a Vec<i32>. The other way to create the Vec is to use the turbofish operator, as is the case with v3 binding in the preceding code.

The turbofish operator in generic functions appears right after the function name and before the parenthesis. Another example of this is the generic parse function from the std::str module. parse can parse values from a string, and many types are able to parse from it, such as i32, f64, usize, and so on, so it's a generic type. So, when using parse, you really need to use the turbofish operator, like so:

// using_generic_func.rs

use std::str;

fn main() {
let num_from_str = str::parse::<u8>("34").unwrap();
println!("Parsed number {}", num_from_str);
}

Something to take note of is that only types that implement the FromStr interface or trait can be passed to the parse function. u8 has an implementation of FromStr, and so we were able to parse it in the preceding code. The parse function uses the FromStr trait to limit types that can be passed to it. We'll get to know how we can mix generics and traits after we're done exploring traits.

With the idea of generics under our belt, let's focus on one of the most ubiquitous features in Rust, traits!

主站蜘蛛池模板: 中方县| 江阴市| 革吉县| 驻马店市| 怀仁县| 高安市| 雷波县| 东乡族自治县| 青州市| 德江县| 房产| 通辽市| 永新县| 镇雄县| 南溪县| 平远县| 仁寿县| 柳江县| 平江县| 渑池县| 蒙城县| 闽清县| 长治县| 昭苏县| 岳阳县| 庄河市| 新闻| 绥阳县| 三门峡市| 西乌珠穆沁旗| 南木林县| 建德市| 玛纳斯县| 延津县| 七台河市| 师宗县| 扬州市| 金堂县| 长春市| 扬中市| 广州市|