ํด๋กœ์ €(Closure)

ํด๋กœ์ € ํ˜น์€ ๋žŒ๋‹คํ‘œํ˜„์‹์€ ์ต๋ช…ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ Fn,FnMut, FnOnce ๋ผ๋Š” ํŠน๋ณ„ํ•œ ํŠธ๋ ˆ์ž‡์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค:

fn apply_with_log(func: impl FnOnce(i32) -> i32, input: i32) -> i32 {
    println!("Calling function on {input}");
    func(input)
}

fn main() {
    let add_3 = |x| x + 3;
    println!("add_3: {}", apply_with_log(add_3, 10));
    println!("add_3: {}", apply_with_log(add_3, 20));

    let mut v = Vec::new();
    let mut accumulate = |x: i32| {
        v.push(x);
        v.iter().sum::<i32>()
    };
    println!("accumulate: {}", apply_with_log(&mut accumulate, 4));
    println!("accumulate: {}", apply_with_log(&mut accumulate, 5));

    let multiply_sum = |x| x * v.into_iter().sum::<i32>();
    println!("multiply_sum: {}", apply_with_log(multiply_sum, 3));
}
This slide should take about 20 minutes.

Fn(์˜ˆ๋ฅผ ๋“ค์–ด add_3)์€ ์บก์ฒ˜๋œ ๊ฐ’์„ ์†Œ๋ชจ๋„ ๋ณ€๊ฒฝ๋„ ํ•˜์ง€ ์•Š๊ณ , ํ˜น์€ ์–ด๋–ค ๊ฒƒ๋„ ์บก์ณํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ์— ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

FnMut(์˜ˆ๋ฅผ ๋“ค์–ด accumulate)๋Š” ์บก์ฒ˜๋œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋™์‹œ์— ํ˜ธ์ถœ ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

FnOnce (์˜ˆ๋ฅผ ๋“ค์–ด multiply_sum)๋Š” ํ•œ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋ฉฐ ์บก์ฒ˜๋œ ๊ฐ’์„ ์†Œ๋ชจํ•ฉ๋‹ˆ๋‹ค.

FnMut ๋Š” FnOnce์˜ ํ•˜์œ„ํƒ€์ž…์ž…๋‹ˆ๋‹ค. Fn์€ FnMut๊ณผ FnOnce์˜ ํ•˜์œ„ ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ์ฆ‰, FnMut๋Š” FnOnce๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ณณ์ด๋ฉด ์–ด๋””์„œ๋‚˜ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๊ณ  Fn์€ FnMut์™€ FnOnce๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ณณ์ด๋ฉด ์–ด๋””๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

When you define a function that takes a closure, you should take FnOnce if you can (i.e. you call it once), or FnMut else, and last Fn. This allows the most flexibility for the caller.

In contrast, when you have a closure, the most flexible you can have is Fn (it can be passed everywhere), then FnMut, and lastly FnOnce.

์ปดํŒŒ์ผ๋Ÿฌ๋Š” ํด๋กœ์ €๊ฐ€ ๋ฌด์—‡์„ ์บก์ณํ•˜๋Š”์ง€์— ๋”ฐ๋ผ Copy(์˜ˆ๋ฅผ ๋“ค์–ด add_3)๊ณผ Clone(์˜ˆ๋ฅผ ๋“ค์–ด multiply_sum)์„ ์•Œ์•„์„œ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋กœ์ ธ๋Š”, ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด, ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์บก์ณ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. move ํ‚ค์›Œ๋“œ๋ฅผ ์“ฐ๋ฉด ๊ฐ’์œผ๋กœ ์บก์ณ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

fn make_greeter(prefix: String) -> impl Fn(&str) {
    return move |name| println!("{} {}", prefix, name);
}

fn main() {
    let hi = make_greeter("Hi".to_string());
    hi("Greg");
}