CodeBlanks Logo Icon CodeBlanks

impl Trait

Specify parameter and return types with impl Trait.

impl Trait

In return position, impl Trait means "I return a single concrete type implementing this trait, but I won't name it". It's used to return types whose names are very long or unwritable, like iterators and closures:

fn ciftler(n: u32) -> impl Iterator<Item = u32> {
    (0..n).filter(|x| x % 2 == 0)
}

fn carpan(k: i32) -> impl Fn(i32) -> i32 {
    move |x| x * k
}

The real type of ciftler is Filter<Range<u32>, {closure}>; closure types can't be named at all.

What does the caller see?

The caller can only use what the trait offers; this gives the freedom to change internal details:

let v: Vec<u32> = ciftler(10).collect();   // [0, 2, 4, 6, 8]
let uc_kat = carpan(3);
println!("{}", uc_kat(7));                  // 21

move makes the closure take ownership of k by copying it; it's needed because k is gone once the function ends.

Practice Hidden return types

Write the ciftler and carpan functions above. Collect ciftler(10) into a vector and multiply 7 with carpan(3); print both separated by a space.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn ciftler(n: u32) -> impl Iterator<Item = u32> {
    (0..n).filter(|x| x % 2 == 0)
}

fn carpan(k: i32) -> impl Fn(i32) -> i32 {
    move |x| x * k
}

fn main() {
    let v: Vec<u32> = ciftler(10).collect();
    let uc_kat = carpan(3);
    println!("{:?} {}", v, uc_kat(7));
}

Expected output

[0, 2, 4, 6, 8] 21

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why doesn't <code>fn f(b: bool) -&gt; impl Display { if b { 5 } else { "beş" } }</code> compile?

  • if isn't an expression
  • It compiles
  • impl Trait must be a single concrete type; i32 and &str differ Correct answer
  • Display can't be returned

Explanation: Returning different types needs dynamic dispatch, like Box<dyn Display>.

2 Return an iterator

Question
fn ciftler(n: u32) -> ____ {
    (0..n).filter(|x| x % 2 == 0)
}
Answer
fn ciftler(n: u32) -> impl Iterator<Item = u32> {
    (0..n).filter(|x| x % 2 == 0)
}

Explanation: impl Iterator<Item = u32> returns an unnamed iterator producing u32.

3 Return type and meaning

Term Meaning
-> impl Iterator<Item = u32> Hidden iterator
-> impl Fn(i32) -> i32 Hidden closure
-> Box<dyn Display> Can be different types
-> Vec<u32> Concrete, owned

All lessons in Intermediate