8.2.1 Capturing
클로저는 본질적으로 유연하고 주해 없이 동작할 수 있는 기능성을 갖는다. 이는 캡쳐가 상황에 맞춰 유연하게 때로는 이동하고 때로는 차용 할 수 있게끔 한다. 클로저들은 변수를 캡쳐 할 수 있다.
- 참조를 통해:
&T
- 가변참조를 통해:
&mut T
- 값을 통해:
T
- by reference:
&T
- by mutable reference:
&mut T
- by value:
T
그들은 우선적으로 참조를 통해 변수를 캡쳐하고 필요에 따라 하위 방법을 취한다.
fn main() { use std::mem; let color = "green"; // `color`를 출력하는 클로저는 `color`를 즉각적 대여(`&`)하고 // `print` 변수에 대여와 클로저를 저장한다. `print`가 범위에서 벗어날 때까지 // 대여는 유지된다. `println!`은 `참조에 의해`서만 요구되므로 // 더 제한적인 것을 강요하지 않는다. let print = || println!("`color`: {}", color); // Call the closure using the borrow. print(); print(); let mut count = 0; // `count`를 증가시키는 클로저는 `&mut count` 또는 `count` 중 하나를 // 취할 수 있지만 `&mut count`이 덜 제한적이므로 이를 취한다. // 즉각적 대여한 `count`. `mut`가 `inc`에 필요한 이유는 `&mut`이 내부에 // 저장되기 때문이다. 따라서 클로저의 호출은 `mut`을 요구하는 클로저를 // 변경한다. let mut inc = || { count += 1; println!("`count`: {}", count); }; // 클로저 호출 . inc(); inc(); //let reborrow = &mut count; // ^ TODO: 해당 라인의 주석을 제거해보세요. // 복사가 아닌 타입. let movable = Box::new(3); // `mem::drop`은 `T`를 요구하므로 이는 값을 취해야 한다. 복사 타입은 // 클로저로 복사되어 원본은 변경되지 않는다. 복사가 아니면 이동되야 하고 // 그래서 `movable`이 즉시 클로저로 이동된다. let consume = || { println!("`movable`: {:?}", movable); mem::drop(movable); }; // `comsume`은 변수를 소비하므로 한번만 호출 될 수 있다. consume(); //consume(); // ^ TODO: 해당 라인의 주석을 제거해보세요. }
See also:
Box
and std::mem::drop