Day6:Closure - 100DayOfRust
Tags: rust
Published: 2019-11-16 17:46:29

## Closure

This is the 6th day and I almost gave up because this "closure" thing is so complicated.

You can see this article here: [Why Rust Closures are (Somewhat) Hard](https://stevedonovan.github.io/rustifications/2018/08/18/rust-closures-are-hard.html)

But finally I think I (somewhat) got it (or I hope so).

## General use case

```rust
fn main() {
    let num_vec = vec![1,2,3,4,5,6];
    let num_arr = [1,2,3,4,5,6];
    
    let finder = |x: &&i32| **x==3;
    
    let found_in_vec = num_vec.iter().find(finder)
                                     .unwrap();
    let found_in_arr = num_arr.iter().find(finder)
                                     .unwrap();
    
    println!("found in vec: {}", found_in_vec);
    println!("found in arr: {}", found_in_arr);
    
    // Pass closure to filter
    let filtered: Vec<&i32> = num_vec.iter()
                                     .filter(|&&x| x % 3 == 0)
                                     .collect();
    println!("Filtered: {:?}", filtered);
    
    // FizzBuzz
    println!("{}", "=".repeat(20));
    let numbers: Vec<i32> = (1..31).collect();
    numbers.iter().for_each(|x| {
        if x % 15 == 0 {
            println!("Fizz Buzz");
        } else if x % 3 == 0 {
            println!("Fizz");
        } else if x % 5 == 0 {
            println!("Buzz");
        } else {
            println!("{}", x);
        }
    });
    
    // Found all numbers divisible by 3
    let div3: Vec<&i32> = numbers.iter()
                                 .filter(|&&x| x % 3 == 0)
                                 .collect();
    println!("Div3: {:?}", div3);
    
    // map a function to range
    let doubled:Vec<i32> = (1..10).map(|x| x*2).collect();
    println!("Doubled: {:?}", doubled);
    
    // sum all even numbers b/t 1 to 10 (10 is not included)
    let sum:i32 = (1..10).filter(|x| x % 2 == 0).sum();
    println!("Sum is {}", sum);
}
```

Result
```
found in vec: 3
found in arr: 3
Filtered: [3, 6]
====================
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
Fizz Buzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
Fizz Buzz
Div3: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
Doubled: [2, 4, 6, 8, 10, 12, 14, 16, 18]
Sum is 20
```

## Closure as input: Fn, FnMut, FnOnce

How variables are captured (by &, by &mut or by value) won't determine which trait (Fn, FnMut, FnOnce) will be used by compiler.

For example, when you use `move`, the variable is captured by value, but if that value is only being used for read, compiler will still use `Fn` attribute, not `FnOnce`, but if that variable is dropped, then compiler will use `FnOnce`

```rust
fn apply<F>(f: F) where F: FnOnce() {
    f();
}

fn sayhi() {
    println!("hi");
}


fn main() {
    let greeting = "hello";
    let mut copied = greeting.to_owned();
    
    let say = || {
        // If just this one line,
        // F could be Fn, FnMut and FnOnce
        println!("{}", greeting);
        
        // With this line, F cannot be Fn anymore
        // needs to be FnMut or FnOnce
        copied.push_str(" world");
        
        // with this line, F needs to be FnOnce
        drop(copied);
    };
        
    apply(say);
    apply(sayhi);
}
```

Result:
```
hello
hi
```

## Closure as output (returned)

```rust
fn create_fn() -> impl Fn() {
    let text = "Fn".to_owned();

    move || println!("This is a: {}", text)
}

fn create_fnmut() -> impl FnMut() {
    let text = "FnMut".to_owned();

    move || println!("This is a: {}", text)
}

fn main() {
    let fn_plain = create_fn();
    let mut fn_mut = create_fnmut();

    fn_plain();
    fn_mut();
}
```

Result:
```
This is a: Fn
This is a: FnMut
```