Rust crashcourse. The rule of three - parameters, iterators and closures

Below is a translation of one part of the Rust Crash Course article series by Michael Snoiman, which focuses on parameter passing mechanisms, iterators and closures regarding how ownership is transferred, and relates to mutability and lifetimes.



I also tried to translate as close to the author's style as possible, but reduced a few interdomes and exclamations that are not very significant for the meaning.


Parameter types



First, I want to deal with a possible misconception. This could be one of those "my brain was damaged by Haskell" delusions that imperative people don't face, so I apologize in advance for my jokes on myself and other Haskellists.







Do the type signatures of the two functions match?







fn foo(mut person: Person) { unimplemented!() }
fn bar(person: Person ) { unimplemented!() }
      
      





: " !". , (exactly the same). (inner mutability) person



, . person



, . : , foo



:







fn main() {
    let alice = Person { name: String::from("Alice"), age: 30 };
    foo(alice); // !
}
      
      





:







fn baz(person: &Person) { unimplemented!() }
fn bin(person: &mut Person) { unimplemented!() }
      
      





-, , baz



, bin



foo



. Person



, Person



. baz



bin



? ? , foo



bar



, , mut



β€” . !







:







fn main() {
    let mut alice = Person { name: String::from("Alice"), age: 30 };
    baz(&alice); // 
    bin(&alice); // !
    bin(&mut alice); //   
}
      
      





bin



, bin



, . . , : , , ( 2).







, :







  • ( ) foo



  • , baz



  • , bin





, , , , , . (. , , ; foo



, baz



bin



person



).







vs.



. , ? ! birthday



, - 1.







#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn birthday_immutable(person: Person) -> Person {
    Person {
        name: person.name,
        age: person.age + 1,
    }
}

fn birthday_mutable(mut person: Person) -> Person {
    person.age += 1;
    person
}

fn main() {
    let alice1 = Person { name: String::from("Alice"), age: 30 };
    println!("Alice 1: {:?}", alice1);
    let alice2 = birthday_immutable(alice1);
    println!("Alice 2: {:?}", alice2);
    let alice3 = birthday_mutable(alice2);
    println!("Alice 3: {:?}", alice3);
}
      
      





:







  • _immutable



    , Person



    , Person



    . Rust, , .
  • , , .
  • alice1



    alice2



    main



    , (move) .
  • alice2



    β€” , , .


vs.



, Rust: β€” (it's unusual). , . , mut



.







, : , ('



) (lifetime parameters), , . , " ". . , Rust Book.







, , , , .







#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn birthday_immutable(person: &mut Person) {
    person.age += 1;
}

fn birthday_mutable<'a>(mut person: &'a mut Person, replacement: &'a mut Person) {
    person = replacement;
    person.age += 1;
}

fn main() {
    let mut alice = Person { name: String::from("Alice"), age: 30 };
    let mut bob = Person { name: String::from("Bob"), age: 20 };
    println!("Alice 1: {:?}, Bob 1: {:?}", alice, bob);
    birthday_immutable(&mut alice);
    println!("Alice 2: {:?}, Bob 2: {:?}", alice, bob);
    birthday_mutable(&mut alice, &mut bob);
    println!("Alice 3: {:?}, Bob 3: {:?}", alice, bob);
}

// does not compile
fn birthday_immutable_broken<'a>(person: &'a mut Person, replacement: &'a mut Person) {
    person = replacement;
    person.age += 1;
}
      
      





birtday_immutable



. , . , . : , , (: person



. , , ).







birthday_mutable



β€” , . : person



replacement



. , person



. , β€” (person = replacement



). , person



, , . , , , , person



:







warning: value passed to `person` is never read
      
      





, main



bob



alice



. ? , . , main



, .







, birthday_immutable_broken



. , . , person



, .







: , , , .







vs.



, , . , , . , , .









:







fn needs_mutable(x: &mut u32) {
    *x *= 2;
}

fn needs_immutable(x: &u32) {
    println!("{}", x);
}

fn main() {
    let mut x: u32 = 5;
    let y: &mut u32 = &mut x;
    needs_immutable(y);
    needs_mutable(y);
    needs_immutable(y);
}
      
      





, , , . y



&mut u32



, needs_immutable



, &u32



. , .







: , , , , ( , ).









:









, . , , . , . , , , . , , .







1



, 10. .







fn double(mut x: u32) {
    x *= 2;
}

fn main() {
    let x = 5;
    double(x);
    println!("{}", x);
}
      
      





: , (asterisk, *



) , (dereference) (. β€” β€” , , ).







//     
fn double(x: &mut u32) {
    //  
    //    ,    
    *x *= 2;
}

fn main() {
    //     
    let mut x = 5;
    //     
    double(&mut x);
    println!("{}", x);
}
      
      







?







fn main() {
    let nums = vec![1, 2, 3, 4, 5];
    for i in nums {
        println!("{}", i);
    }
}
      
      





, 1 5. ?







fn main() {
    for i in 1..3 {
        let nums = vec![1, 2, 3, 4, 5];
        for j in nums {
            println!("{},{}", i, j);
        }
    }
}
      
      





1,1



, 1,2



, ..., 2,1



, ..., 2,5



. - . nums



. ?







fn main() {
    let nums = vec![1, 2, 3, 4, 5];
    for i in 1..3 {
        for j in nums {
            println!("{},{}", i, j);
        }
    }
}
      
      





. .







error[E0382]: use of moved value: `nums`
 --> main.rs:4:18
  |
4 |         for j in nums {
  |                  ^^^^ value moved here in previous iteration of loop
  |
  = note: move occurs because `nums` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

error: aborting due to previous error
      
      





. , , (move) nums



. , , nums



. .







, nums



for



. , . . , nums



. ()!







nums



, (borrowing)? , !







fn main() {
    let nums = vec![1, 2, 3, 4, 5];
    for i in 1..3 {
        for j in &nums {
            println!("{},{}", i, j);
        }
    }
}
      
      





, : j



? . println!



, :







let _: u32 = j;
      
      





error[E0308]: mismatched types
 --> src/main.rs:5:26
  |
5 |             let _: u32 = j;
  |                    ---   ^
  |                    |     |
  |                    |     expected `u32`, found `&{integer}`
  |                    |     help: consider dereferencing the borrow: `*j`
  |                    expected due to this
      
      





, :







let _: &u32 = j;
      
      





nums



, , . " " ? !







fn main() {
    let nums = vec![1, 2, 3, 4, 5];
    for i in 1..3 {
        for j in &mut nums {
            let _: &mut u32 = j;
            println!("{},{}", i, j);
            *j *= 2;
        }
    }
}
      
      





. . . , , .







fn main() {
    // nums   
    let mut nums = vec![1, 2, 3, 4, 5];
    for i in 1..3 {
        for j in &mut nums {
            let _: &mut u32 = j;
            println!("{},{}", i, j);
            *j *= 2;
        }
    }
}
      
      





, . , , .









vec



, . ,







for j in &mut nums {
```Rust
 
```Rust
for j in nums.iter_mut() {
      
      





:







pub fn iter_mut(&mut self) -> IterMut<T>
      
      





iter()



, :







fn main() {
    let nums = vec![1, 2, 3, 4, 5];
    for i in 1..3 {
        for j in nums.iter() {
            let _: &u32 = j;
            println!("{}, {}", i, j);
        }
    }
}
      
      





? into_iter()



. , (into) , ( , nums



Vec



). . , let nums



:







fn main() {
    let nums = vec![1, 2, 3, 4, 5];
    for i in 1..3 {
        for j in nums.into_iter() {
            println!("{}, {}", i, j);
        }
    }
}
      
      





fn main() {
    for i in 1..3 {
        //   nums   into_iter()
        //       
        let nums = vec![1, 2, 3, 4, 5];
        for j in nums.into_iter() {
            println!("{}, {}", i, j);
        }
    }
}
      
      





for



, . for



, . into_iter()



, IntoIterator



. for x in y



, into_iter()



y



. , Iterator



.







2



, IntoIterator



InfiniteUnit



. Iterator



! , . ( : , ).







struct InfiniteUnit;

fn main() {
    let mut count = 0;
    for _ in InfiniteUnit {
        count += 1;
        println!("count == {}", count);
        if count >= 5 {
            break;
        }
    }
}
      
      





struct InfiniteUnit;

impl IntoIterator for InfiniteUnit {
    type Item = ();
    type IntoIter = InfiniteUnitIter;

    fn into_iter(self) -> Self::IntoIter {
        InfiniteUnitIter
    }
}

struct InfiniteUnitIter;

impl Iterator for InfiniteUnitIter {
    type Item = ();

    fn next(&mut self) -> Option<()> {
        Some(())
    }
}

fn main() {
    let mut count = 0;
    for _ in InfiniteUnit {
        count += 1;
        println!("count == {}", count);
        if count >= 5 {
            break;
        }
    }
}
      
      





, .. repeat



, . .







struct InfiniteUnit;

impl IntoIterator for InfiniteUnit {
    type Item = ();
    type IntoIter = std::iter::Repeat<()>;

    fn into_iter(self) -> Self::IntoIter {
        std::iter::repeat(())
    }
}

fn main() {
    let mut count = 0;
    for _ in InfiniteUnit {
        count += 1;
        println!("count == {}", count);
        if count >= 5 {
            break;
        }
    }
}
      
      







, (flavors), :







  • into_iter



    β€” ,
  • iter



    β€”
  • iter_mut()



    β€”


iter_mut()



, .









, . , (local scope). .







: , , , . , , , . , . , , , JS.







. , ?







fn main() {
    fn say_hi() {
        let msg: &str = "Hi!";
        println!("{}", msg);
    };

    say_hi();
    say_hi();
}
      
      





. :







fn main() {
    let msg: &str = "Hi!";
    fn say_hi() {
        println!("{}", msg);
    };
    say_hi();
    say_hi();
}
      
      





, :







error[E0434]: can't capture dynamic environment in a fn item
 --> main.rs:4:24
  |
4 |         println!("{}", msg);
  |                        ^^^
  |
  = help: use the `|| { ... }` closure form instead

error: aborting due to previous error
      
      





, : . :







fn main() {
    let msg: &str = "Hi!";
    let say_hi = || {
        println!("{}", msg);
    };
    say_hi();
    say_hi();
}
      
      





( ||



), . .







: let say_hi = || println!("{}", msg);



, .







3



, say_hi



: msg



. fn



.







:







fn main() {
    let msg: &str = "Hi!";
    let say_hi = |msg| println!("{}", msg);
    say_hi(msg);
    say_hi(msg);
}
      
      





:







fn main() {
    let msg: &str = "Hi!";
    fn say_hi(msg: &str) {
        println!("{}", msg);
    }
    say_hi(msg);
    say_hi(msg);
}
      
      





, say_hi



.









say_hi



? , : , . , , u32



, :







fn main() {
    let msg: &str = "Hi!";
    let say_hi: u32 = |msg| println!("{}", msg);
}
      
      





:







error[E0308]: mismatched types
 --> src/main.rs:3:23
  |
3 |     let say_hi: u32 = |msg| println!("{}", msg);
  |                 ---   ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found closure
  |                 |
  |                 expected due to this
  |
  = note: expected type `u32`
          found closure `[closure@src/main.rs:3:23: 3:48]`
      
      





[closure@main.rs:3:23: 3:48]



… , :







fn main() {
    let msg: &str = "Hi!";
    let say_hi: [closure@main.rs:3:23: 3:48] = |msg| println!("{}", msg);
}
      
      





:







error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `@`
 --> src/main.rs:3:25
  |
3 |     let say_hi: [closure@main.rs:3:23: 3:48] = |msg| println!("{}", msg);
  |         ------          ^ expected one of 7 possible tokens
  |         |
  |         while parsing the type for `say_hi`
      
      





. ?









. . . , ? , :







fn main() {
    let say_message = |msg: &str| println!("{}", msg);
    call_with_hi(say_message);
    call_with_hi(say_message);
}

fn call_with_hi<F>(f: F) {
    f("Hi!");
}
      
      





msg



. , -, , . . , .







F



, . F



, . , :







error[E0618]: expected function, found `F`
 --> src/main.rs:8:5
  |
7 | fn call_with_hi<F>(f: F) {
  |                    - `F` defined here
8 |     f("Hi!");
  |     ^-------
  |     |
  |     call expression requires function
      
      





: , F



. - , : Fn



!







fn call_with_hi<F>(f: F)
    where F: Fn(&str) -> ()
{
    f("Hi!");
}
      
      





F



, , &str



, . , -, .







fn call_with_hi<F>(f: F)
    where F: Fn(&str)
{
    f("Hi!");
}
      
      





, Fn



, .







4



say_message



main



, .







fn main() {
    call_with_hi(say_message);
    call_with_hi(say_message);
}

fn say_message(msg: &str) {
    println!("{}", msg);
}

fn call_with_hi<F>(f: F)
    where F: Fn(&str)
{
    f("Hi!");
}
      
      





say_message



, . .







fn main() {
    let name = String::from("Alice");
    let say_something = |msg: &str| println!("{}, {}", msg, name);
    call_with_hi(say_something);
    call_with_hi(say_something);
    call_with_bye(say_something);
    call_with_bye(say_something);
}

fn call_with_hi<F>(f: F)
    where F: Fn(&str)
{
    f("Hi");
}

fn call_with_bye<F>(f: F)
    where F: Fn(&str)
{
    f("Bye");
}
      
      







-? !







fn main() {
    let mut count = 0;

    for _ in 1..6 {
        count += 1;
        println!("You are visitor #{}", count);
    }
}
      
      





, ! .







fn main() {
    let mut count = 0;
    let visit = || {
        count += 1;
        println!("You are visitor #{}", count);
    };

    for _ in 1..6 {
        visit();
    }
}
      
      





:







error[E0596]: cannot borrow `visit` as mutable, as it is not declared as mutable
 --> src/main.rs:9:9
  |
3 |     let visit = || {
  |         ----- help: consider changing this to be mutable: `mut visit`
...
9 |         visit();
  |         ^^^^^ cannot borrow as mutable
      
      





… ? , . , . - . ?







: visit



(captured) count



. , visit



count



. . ? ? , , :







fn main() {
    let mut count = 0;
    let visit = || {
        count += 1;
        println!("You are visitor #{}", count);
    };

    call_five_times(visit);
}

fn call_five_times<F>(f: F)
    where F: Fn()
{
    for _ in 1..6 {
        f();
    }
}
      
      





:







error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
      
      





! : , (Fn



), , (FnMut



). Fn



FnMut



where



. :







error[E0596]: cannot borrow immutable argument `f` as mutable
  --> main.rs:16:9
   |
11 | fn call_five_times<F>(f: F)
   |                       - help: make this binding mutable: `mut f`
...
16 |         f();
   |         ^ cannot borrow mutably
      
      





, . mut



f: F



.







?



Fn



FnMut



?







|| println!("Hello World!");
      
      





- , , Fn



. , call_five_times



, FnMut



, ? β€” ! , :







call_five_times(|| println!("Hello World!"));
      
      





, Fn



FnMut



. , : , , , . , (FnMut



) , (Fn



) .







(subtyping)? , .







?



, " ", . , , . , , . β€” (value/move semantics).







, (moves) . String



(Copy



able) u32



. , . , .







fn main() {
    let name = String::from("Alice");

    let welcome = || {
        let name = name; //   
        println!("Welcome, {}", name);
    };

    welcome();
}
      
      





name



welcome



. let name = name;



. , name



? :







fn main() {
    let name1 = String::from("Alice");

    let welcom = || {
        let mut name2 = name1;
        name2 += " and Bob";
        println!("Welcome, {}", name2);
    };

    welcome();
}
      
      





name1



. name2



, , . β€” , . ? name1



, welcome()



.









. call_five_times



? welcome



:







fn main() {
    let name = String::from("Alice");

    let welcome = || {
        let mut name = name;
        name += " and Bob";
        println!("Welcome, {}", name);
    };

    call_five_times(welcome);
}

fn call_five_times<F>(f: F)
where
    F: Fn(),
{
    for _ in 1..6 {
        f();
    }
}
      
      





, FnOnce



:







error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
  --> main.rs:4:19
   |
4  |     let welcome = || {
   |                   ^^ this closure implements `FnOnce`, not `Fn`
5  |         let mut name = name;
   |                        ---- closure is `FnOnce` because it moves the variable `name` out of its environment
...
10 |     call_five_times(welcome);
   |     --------------- the requirement to implement `Fn` derives from here
      
      





Fn()



FnOnce()



, ? !







error[E0382]: use of moved value: `f`
  --> main.rs:18:9
   |
18 |         f();
   |         ^ value moved here in previous iteration of loop
   |
   = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
      
      





f



. , f



, . , . FnOnce



.







, :







fn main() {
    let name = String::from("Alice");

    let welcome = || {
        let mut name = name;
        name += " and Bob";
        println!("Welcome, {}", name);
    };

    call_once(welcome);
}

fn call_once<F>(f: F)
where
    F: FnOnce()
{
    f();
}
      
      





.









, Fn



FnMut



, , , . , Fn



FnOnce



FnOnce



, , , , .







move





, , , ( ). "Rust by Example" . , .







, . , , . , . , , . , :







fn pass_by_value(_x: String) {}
fn pass_by_ref(_x: &String) {}

fn pass_by_mut_ref(x: &mut String) {
    pass_by_ref(x);     //   
    pass_by_value(*x);  //    
}

fn main() {}
      
      





, . , (implicit). , . . , - , , (captured), , , .







, , , , :







  • ,
  • , . , (is dropped), .
  • , - ( , ).


, :







, β€” .

, , . : , . :







fn main() {
    // owned by main
    let name_outer = String::from("Alice");

    let say_hi || {
        // force a move, again, we'll get smarter in a second
        let name_inner = name_outer;
        println!("Hello, {}", name_inner);
    };

    // main no longer owns name_outer, try this:
    println!("Using name from main: {}", name_outer); // error!

    // but name_inner lives on, in say_hi!
    say_hi(); // success
}
      
      





, () β€” name_outer



, .







, . let name_inner = name_outer;



. name_outer



. , , name_outer



. ( say_hi()



). , . . , , name_outer



:







fn main() {
    // owned by main
    let name_outer = String::from("Alice");

    let say_hi || {
        // use by ref
        let name_inner = &name_outer;
        println!("Hello, {}", name_inner);
    };

    // main still owns name_outer, this is fine
    println!("Using name from main: {}", name_outer); // success

    // but name_inner lives on, in say_hi!
    say_hi(); // success
    say_hi(); // success
}
      
      





, , name_outer



say_hi



, !







fn main() {
    let say_hi = { //     
        //
        let name_outer = String::from("Alice");

        //  ,     
        || {
            // use by ref
            let name_inner = &name_outer;
            println!("Hello, {}", name_inner);
        }
    };

    //  ,   name_outer      
    // println!("Using name from main: {}", name_outer); // error!

    say_hi();
    say_hi();
}
      
      





, - : " , , , ( β€” .)". , . , move



:







fn main() {
    let say_hi = {
        let name_outer = String::from("Alice");

        move || {
            let name_inner = &name_outer;
            println!("Hello, {}", name_inner);
        }
    }

    say_hi();
    say_hi();
}
      
      





name_outer



. - , , .







. move



, , . , :







fn main() {
    let name = String::from("Alice");
    let _ = move || { println!("Hello, {}", name) };

    println!("Using name from main: {}", name); // error!
}

      
      





Rust



, . . , , , ? , : . Rust by Example:







, , .







let name_inner = name_outer;



. , , ( ), . .







  • , .
  • , , .
  • , , .


, . , . , , , , .







, , move



, .







, , , move



. , , : " , " .







: ,



:







  • , .
  • , , , , .
  • , , . , , .
  • , move



    .
  • :

    • - , FnOnce



      .
    • , - , FnMut



      , FnOnce



      .
    • Fn



      , FnMut



      FnOnce



      .


, , , , , . Rust by example.







, :







fn call_fn<F>(f: F) where F: Fn() {
    f()
}

fn call_fn_mut<F>(mut f: F) where F: FnMut() {
    f()
}

fn call_fn_once<F>(f: F) where F: FnOnce() {
    f()
}
      
      







main



:







fn main() {
    let name = String::from("Alice");
    let say_hi = || println!("Hello, {}", name);
    call_fn(say_hi);
    call_fn_mut(say_hi);
    call_fn_once(say_hi);
}
      
      





name



, say_hi



, , , , name



. , say_hi



Fn



, FnMut



FnOnce



, .







// bad!
fn main() {
    let say_hi = {
        let name = String::from("Alice");
        || println!("Hello, {}", name)
    };
}
      
      





, . name



. , , , . , , :







fn main() {
    let say_hi = {
        let name = String::from("Alice");
        || {
            let name = name;
            println!("Hello, {}", name)
        }
    };

    // call_fn(say_hi);
    // call_fn_mut(say_hi);
    call_fn_once(say_hi);
}
      
      





FnOnce



, , . ! name



, ( - β€” ):







fn main() {
    let say_hi = {
        let name = String::from("Alice");
        move || println!("Hello, {}", name)
    };

    call_fn(&say_hi);
    call_fn_mut(&say_hi);
    call_fn_once(&say_hi);
}
      
      





, Fn



, FnMut



FnOnce



. , say_hi



, call_fn



. ( ), , , . ( β€” .) , .







fn main() {
    let say_hi = {
        let name = String::from("Alice");
        || std::mem::drop(name)
    };
    //call_fn(say_hi);
    //call_fn_mut(say_hi);
    call_fn_once(say_hi);
}
      
      





drop



name



. , , , . , move



, .







fn main() {
    let mut say_hi = {
        let mut name = String::from("Alice");
        move || {
            name += " and Bob";
            println!("Hello, {}", name);
        }
    };
    //call_fn(say_hi);
    call_fn_mut(&mut say_hi);
    call_fn_once(&mut say_hi);
}
      
      





+=



String



, . . , name



. name



, (move



) . say_hi



, mut



.







say_hi



, &mut



, (1) , , (2) . call_fn



, FnMut



FnOnce



, Fn



.







? " and Bob"



name



?







fn main() {
    let mut name = String::from("Alice");
    let mut say_hi = || {
        name += " and Bob";
        println!("Hello, {}", name);
    };
    //call_fn(say_hi);
    call_fn_mut(&mut say_hi);
    call_fn_once(&mut say_hi);
}
      
      





name



, .







// bad!
fn main() {
    let mut name = String::from("Alice");
    let mut say_hi = || {
        name += " and Bob";
        println!("Hello, {}", name);
    };
    //call_fn(say_hi);
    call_fn_mut(&mut say_hi);
    call_fn_once(&mut say_hi);

    println!("And now name is: {}", name);
}
      
      





say_hi



, println!



, name



, . - (lexical lifetimes). ( ) " " (non-lexical lifetimes), #![feature(nll)]



. , :







fn main() {
    let mut name = String::from("Alice");
    {
        let mut say_hi = || {
            name += " and Bob";
            println!("Hello, {}", name);
        };
        //call_fn(say_hi);
        call_fn_mut(&mut say_hi);
        call_fn_once(&mut say_hi);
    }

    println!("And now name is: {}", name);
}
      
      





( , ) ( β€” .):







fn main() {
    let mut name = String::from("Alice");
    let mut say_hi = || {
        println!("Hello, {}", name); // use by ref
        name += " and Bob"; // use by mut ref
        std::mem::drop(name); // use by value
    };

    //call_fn(say_hi);
    //call_fn_mut(say_hi);
    call_fn_oce(say_hi);
}
      
      





, , . , , , .







?



, . - . Rust Book:







, Fn



-, Fn



, , , , , FnMut



FnOnce



.

, " , ". , β€” FnOnce



. , .







, Rust by Example.









, Fn



. , Fn



FnMut



, FnMut



FnOnce



.







  • FnOnce



  • FnMut



  • Fn





, , , . , Fn



.







5



Now that we have added everything we learned about iterators and closures, change line 5 (which starts with for i in



) so that the program prints the numbers 2,4,6,...,20



twice.







fn main() {
    let nums: Vec<u32> = (1..11).collect();

    for _ in 1..3 {
        for i in nums.map(todo!()) {
            println!("{}", i);
        }
    }
}
      
      





Decision

:







error[E0599]: no method named `map` found for type `std::vec::Vec<u32>` in the current scope
 --> main.rs:5:23
  |
5 |         for i in nums.map(todo!()) {
  |                       ^^^
  |
  = note: the method `map` exists but the following trait bounds were not satisfied:
          `&mut std::vec::Vec<u32> : std::iter::Iterator`
          `&mut [u32] : std::iter::Iterator`
      
      





, nums



. : into_iter()



, iter()



iter_mut()



. , , iter()



. nums.map



nums.iter().map



, todo!()



.







, . : |x| x * 2



. : FnOnce



, FnMut



Fn



?








All Articles