Generics and `where` syntax
Generics are powerful thing for all languages. With generics you can create awesome algorithms. Rust has all requirements about generics and with that Rust took it one step further.
So what the hell is where thing? Just imagine that, you want to use an Iterator as generic but Iterator‘s Item type must be a trait? You can’t specify Item type with classical syntax.
fn first_or_default<I: Iterator>(mut i: I) -> I::Item
{
i.next().unwrap_or_else(I::Item::default)
}
This generates compiler error because Item doesn’t have the default field. If you want to use this you have to specify the I::Item‘s type implemented the Default trait. So let’s fix this code:
fn first_or_default<I>(mut i: I) -> I::Item
where
I: Iterator,
I::Item: Default,
{
i.next().unwrap_or_else(I::Item::default)
}
As you can see the where syntax allows us to specify more deeply types. You can check HERE for detailed information and examples.
You can play with that code also:
trait Bar {
fn bar(&self) -> Vec<i32>;
}
struct Foo;
struct Baz;
impl Bar for Foo {
fn bar(&self) -> Vec<i32> {
vec![1, 2, 3]
}
}
impl Bar for Baz {
fn bar(&self) -> Vec<i32> {
vec![4, 5, 6, 7]
}
}
fn print_impl(bar: impl Bar) {
println!("print_impl Bar: {:?}", bar.bar());
}
fn print_gnrc<B: Bar>(bar: B) {
println!("print_gnrc Bar: {:?}", bar.bar());
}
fn print_whre<B>(bar: B)
where
B: Bar,
{
println!("print_whre Bar: {:?}", bar.bar());
}
fn main() {
let foo1 = Foo;
let baz1 = Baz;
print_impl(foo1);
print_impl(baz1);
print_gnrc(Foo);
print_gnrc(Baz);
print_whre(Foo);
print_whre(Baz);
}
// ⏯️ play
Happy coding…
0 yorum